solace-agent-mesh 1.6.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 (481) 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/app_llm_agent.py +26 -0
  7. solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +165 -1
  8. solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
  9. solace_agent_mesh/agent/adk/callbacks.py +852 -109
  10. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +234 -36
  11. solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +52 -5
  12. solace_agent_mesh/agent/adk/mcp_content_processor.py +1 -1
  13. solace_agent_mesh/agent/adk/models/lite_llm.py +77 -21
  14. solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
  15. solace_agent_mesh/agent/adk/runner.py +85 -20
  16. solace_agent_mesh/agent/adk/schema_migration.py +88 -0
  17. solace_agent_mesh/agent/adk/services.py +94 -18
  18. solace_agent_mesh/agent/adk/setup.py +281 -65
  19. solace_agent_mesh/agent/adk/stream_parser.py +231 -37
  20. solace_agent_mesh/agent/adk/tool_wrapper.py +3 -0
  21. solace_agent_mesh/agent/protocol/event_handlers.py +472 -137
  22. solace_agent_mesh/agent/proxies/a2a/app.py +3 -2
  23. solace_agent_mesh/agent/proxies/a2a/component.py +572 -75
  24. solace_agent_mesh/agent/proxies/a2a/config.py +80 -4
  25. solace_agent_mesh/agent/proxies/base/app.py +3 -2
  26. solace_agent_mesh/agent/proxies/base/component.py +188 -22
  27. solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
  28. solace_agent_mesh/agent/sac/app.py +91 -3
  29. solace_agent_mesh/agent/sac/component.py +591 -157
  30. solace_agent_mesh/agent/sac/patch_adk.py +8 -16
  31. solace_agent_mesh/agent/sac/task_execution_context.py +146 -4
  32. solace_agent_mesh/agent/tools/__init__.py +3 -0
  33. solace_agent_mesh/agent/tools/audio_tools.py +3 -3
  34. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +710 -171
  35. solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
  36. solace_agent_mesh/agent/tools/dynamic_tool.py +2 -0
  37. solace_agent_mesh/agent/tools/peer_agent_tool.py +82 -15
  38. solace_agent_mesh/agent/tools/time_tools.py +126 -0
  39. solace_agent_mesh/agent/tools/tool_config_types.py +57 -2
  40. solace_agent_mesh/agent/tools/web_search_tools.py +279 -0
  41. solace_agent_mesh/agent/tools/web_tools.py +125 -17
  42. solace_agent_mesh/agent/utils/artifact_helpers.py +248 -6
  43. solace_agent_mesh/agent/utils/context_helpers.py +17 -0
  44. solace_agent_mesh/assets/docs/404.html +6 -6
  45. solace_agent_mesh/assets/docs/assets/css/{styles.906a1503.css → styles.8162edfb.css} +1 -1
  46. solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
  47. solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/17896441.e612dfb4.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
  51. solace_agent_mesh/assets/docs/assets/js/{17896441.a5e82f9b.js.LICENSE.txt → 2279.550aa580.js.LICENSE.txt} +6 -0
  52. solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
  53. solace_agent_mesh/assets/docs/assets/js/2987107d.a80604f9.js +1 -0
  54. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
  55. solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
  56. solace_agent_mesh/assets/docs/assets/js/3ac1795d.7f7ab1c1.js +1 -0
  57. solace_agent_mesh/assets/docs/assets/js/3ff0015d.e53c9b78.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/41adc471.0e95b87c.js +1 -0
  59. solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
  60. solace_agent_mesh/assets/docs/assets/js/49eed117.493d6f99.js +1 -0
  61. solace_agent_mesh/assets/docs/assets/js/{509e993c.4c7a1a6d.js → 509e993c.a1fbf45a.js} +1 -1
  62. solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
  63. solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.js +1 -0
  64. solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
  65. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
  66. solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
  67. solace_agent_mesh/assets/docs/assets/js/631738c7.fa471607.js +1 -0
  68. solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
  69. solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
  70. solace_agent_mesh/assets/docs/assets/js/6a520c9d.b6e3f2ce.js +1 -0
  71. solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
  72. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.a5b36a60.js +1 -0
  73. solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
  74. solace_agent_mesh/assets/docs/assets/js/71da7b71.374b9d54.js +1 -0
  75. solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
  76. solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
  77. solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
  78. solace_agent_mesh/assets/docs/assets/js/81a99df0.7ed65d45.js +1 -0
  79. solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
  80. solace_agent_mesh/assets/docs/assets/js/8b032486.91a91afc.js +1 -0
  81. solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
  82. solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.js +1 -0
  83. solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
  84. solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
  85. solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
  86. solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
  87. solace_agent_mesh/assets/docs/assets/js/ad87452a.9d73dad6.js +1 -0
  88. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
  89. solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
  90. solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
  91. solace_agent_mesh/assets/docs/assets/js/da0b5bad.b62f7b08.js +1 -0
  92. solace_agent_mesh/assets/docs/assets/js/dd817ffc.c37a755e.js +1 -0
  93. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.b682e9c2.js +1 -0
  94. solace_agent_mesh/assets/docs/assets/js/de915948.44a432bc.js +1 -0
  95. solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
  96. solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
  97. solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
  98. solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
  99. solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
  100. solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
  101. solace_agent_mesh/assets/docs/assets/js/f284c35a.cc97854c.js +1 -0
  102. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.74710fc1.js +1 -0
  103. solace_agent_mesh/assets/docs/assets/js/main.d634009f.js +2 -0
  104. solace_agent_mesh/assets/docs/assets/js/runtime~main.27bb82a7.js +1 -0
  105. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +68 -68
  106. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +50 -50
  107. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +42 -42
  108. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +55 -55
  109. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +82 -68
  110. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
  111. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +67 -50
  112. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/research-tools/index.html +136 -0
  113. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +178 -144
  114. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +43 -42
  115. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +20 -18
  116. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +23 -23
  117. solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
  118. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +45 -45
  119. solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +182 -0
  120. solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
  121. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +208 -125
  122. solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
  123. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +28 -49
  124. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -30
  125. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +14 -14
  126. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/index.html +47 -0
  127. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
  128. solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +90 -0
  129. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -16
  130. solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
  131. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +38 -38
  132. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +162 -171
  133. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +67 -49
  134. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +17 -17
  135. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +51 -51
  136. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +22 -22
  137. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +27 -27
  138. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +135 -135
  139. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +66 -66
  140. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +51 -51
  141. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +50 -38
  142. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +86 -86
  143. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +51 -51
  144. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +24 -24
  145. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +30 -30
  146. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +44 -44
  147. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
  148. solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +86 -0
  149. solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +67 -0
  150. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +23 -19
  151. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +40 -37
  152. solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
  153. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +112 -87
  154. solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +440 -0
  155. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +87 -64
  156. solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +62 -0
  157. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +44 -44
  158. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +39 -37
  159. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +30 -30
  160. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +18 -18
  161. solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
  162. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +311 -0
  163. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +39 -42
  164. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +14 -14
  165. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +27 -25
  166. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +69 -69
  167. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +72 -72
  168. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +251 -0
  169. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +88 -0
  170. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +42 -42
  171. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +20 -20
  172. solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
  173. solace_agent_mesh/assets/docs/lunr-index-1768329217460.json +1 -0
  174. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  175. solace_agent_mesh/assets/docs/search-doc-1768329217460.json +1 -0
  176. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  177. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  178. solace_agent_mesh/cli/__init__.py +1 -1
  179. solace_agent_mesh/cli/commands/add_cmd/__init__.py +3 -1
  180. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +6 -1
  181. solace_agent_mesh/cli/commands/add_cmd/proxy_cmd.py +100 -0
  182. solace_agent_mesh/cli/commands/docs_cmd.py +4 -1
  183. solace_agent_mesh/cli/commands/eval_cmd.py +1 -1
  184. solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
  185. solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
  186. solace_agent_mesh/cli/commands/init_cmd/env_step.py +30 -3
  187. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +3 -4
  188. solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
  189. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +16 -3
  190. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +2 -1
  191. solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
  192. solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +3 -3
  193. solace_agent_mesh/cli/commands/run_cmd.py +64 -49
  194. solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
  195. solace_agent_mesh/cli/main.py +15 -0
  196. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-BTf6dqwp.js → authCallback-KnKMP_vb.js} +1 -1
  197. solace_agent_mesh/client/webui/frontend/static/assets/client-DpBL2stg.js +25 -0
  198. solace_agent_mesh/client/webui/frontend/static/assets/main-Cd498TV2.js +435 -0
  199. solace_agent_mesh/client/webui/frontend/static/assets/main-rSf8Vu29.css +1 -0
  200. solace_agent_mesh/client/webui/frontend/static/assets/vendor-CGk8Suyh.js +565 -0
  201. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  202. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  203. solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
  204. solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
  205. solace_agent_mesh/common/a2a/events.py +2 -1
  206. solace_agent_mesh/common/a2a/protocol.py +5 -0
  207. solace_agent_mesh/common/a2a/types.py +2 -1
  208. solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +23 -6
  209. solace_agent_mesh/common/a2a_spec/schemas/feedback_event.json +51 -0
  210. solace_agent_mesh/common/agent_registry.py +38 -11
  211. solace_agent_mesh/common/data_parts.py +144 -4
  212. solace_agent_mesh/common/error_handlers.py +83 -0
  213. solace_agent_mesh/common/exceptions.py +24 -0
  214. solace_agent_mesh/common/oauth/__init__.py +17 -0
  215. solace_agent_mesh/common/oauth/oauth_client.py +408 -0
  216. solace_agent_mesh/common/oauth/utils.py +50 -0
  217. solace_agent_mesh/common/rag_dto.py +156 -0
  218. solace_agent_mesh/common/sac/sam_component_base.py +97 -19
  219. solace_agent_mesh/common/sam_events/event_service.py +2 -2
  220. solace_agent_mesh/common/services/employee_service.py +1 -1
  221. solace_agent_mesh/common/utils/embeds/constants.py +1 -0
  222. solace_agent_mesh/common/utils/embeds/converter.py +1 -8
  223. solace_agent_mesh/common/utils/embeds/modifiers.py +4 -28
  224. solace_agent_mesh/common/utils/embeds/resolver.py +152 -31
  225. solace_agent_mesh/common/utils/embeds/types.py +9 -0
  226. solace_agent_mesh/common/utils/log_formatters.py +20 -0
  227. solace_agent_mesh/common/utils/mime_helpers.py +12 -5
  228. solace_agent_mesh/common/utils/pydantic_utils.py +90 -3
  229. solace_agent_mesh/common/utils/rbac_utils.py +69 -0
  230. solace_agent_mesh/common/utils/templates/__init__.py +8 -0
  231. solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
  232. solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
  233. solace_agent_mesh/config_portal/backend/common.py +12 -0
  234. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-CljP4_mv.js +103 -0
  235. solace_agent_mesh/config_portal/frontend/static/client/assets/{components-Rk0n-9cK.js → components-CaC6hG8d.js} +22 -22
  236. solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-mvZjNKiz.js → entry.client-H_TM0YBt.js} +3 -3
  237. solace_agent_mesh/config_portal/frontend/static/client/assets/{index-DzNKzXrc.js → index-CnFykb2v.js} +16 -16
  238. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-f8439d40.js +1 -0
  239. solace_agent_mesh/config_portal/frontend/static/client/assets/root-BIMqslJB.css +1 -0
  240. solace_agent_mesh/config_portal/frontend/static/client/assets/root-mJmTIdIk.js +10 -0
  241. solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
  242. solace_agent_mesh/core_a2a/service.py +3 -2
  243. solace_agent_mesh/gateway/adapter/__init__.py +1 -0
  244. solace_agent_mesh/gateway/adapter/base.py +170 -0
  245. solace_agent_mesh/gateway/adapter/types.py +230 -0
  246. solace_agent_mesh/gateway/base/app.py +39 -2
  247. solace_agent_mesh/gateway/base/auth_interface.py +103 -0
  248. solace_agent_mesh/gateway/base/component.py +1027 -151
  249. solace_agent_mesh/gateway/generic/__init__.py +1 -0
  250. solace_agent_mesh/gateway/generic/app.py +50 -0
  251. solace_agent_mesh/gateway/generic/component.py +894 -0
  252. solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
  253. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_project_users_table.py +72 -0
  254. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +109 -0
  255. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +26 -0
  256. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_projects_table.py +135 -0
  257. solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
  258. solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
  259. solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
  260. solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
  261. solace_agent_mesh/gateway/http_sse/alembic.ini +0 -36
  262. solace_agent_mesh/gateway/http_sse/app.py +40 -11
  263. solace_agent_mesh/gateway/http_sse/component.py +285 -160
  264. solace_agent_mesh/gateway/http_sse/dependencies.py +149 -114
  265. solace_agent_mesh/gateway/http_sse/main.py +68 -450
  266. solace_agent_mesh/gateway/http_sse/repository/__init__.py +19 -1
  267. solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
  268. solace_agent_mesh/gateway/http_sse/repository/entities/project.py +81 -0
  269. solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +47 -0
  270. solace_agent_mesh/gateway/http_sse/repository/entities/session.py +26 -3
  271. solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
  272. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +47 -0
  273. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +114 -6
  274. solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +13 -0
  275. solace_agent_mesh/gateway/http_sse/repository/models/project_model.py +51 -0
  276. solace_agent_mesh/gateway/http_sse/repository/models/project_user_model.py +75 -0
  277. solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
  278. solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +8 -2
  279. solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
  280. solace_agent_mesh/gateway/http_sse/repository/project_repository.py +172 -0
  281. solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +186 -0
  282. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +177 -11
  283. solace_agent_mesh/gateway/http_sse/repository/task_repository.py +86 -2
  284. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +38 -7
  285. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +256 -58
  286. solace_agent_mesh/gateway/http_sse/routers/auth.py +168 -134
  287. solace_agent_mesh/gateway/http_sse/routers/config.py +302 -8
  288. solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
  289. solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
  290. solace_agent_mesh/gateway/http_sse/routers/dto/requests/project_requests.py +48 -0
  291. solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +14 -1
  292. solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
  293. solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +31 -0
  294. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +5 -2
  295. solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
  296. solace_agent_mesh/gateway/http_sse/routers/feedback.py +133 -2
  297. solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
  298. solace_agent_mesh/gateway/http_sse/routers/projects.py +768 -0
  299. solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
  300. solace_agent_mesh/gateway/http_sse/routers/sessions.py +167 -7
  301. solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
  302. solace_agent_mesh/gateway/http_sse/routers/sse.py +131 -8
  303. solace_agent_mesh/gateway/http_sse/routers/tasks.py +670 -18
  304. solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
  305. solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
  306. solace_agent_mesh/gateway/http_sse/routers/visualization.py +92 -9
  307. solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
  308. solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
  309. solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
  310. solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
  311. solace_agent_mesh/gateway/http_sse/services/project_service.py +930 -0
  312. solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
  313. solace_agent_mesh/gateway/http_sse/services/session_service.py +361 -12
  314. solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
  315. solace_agent_mesh/gateway/http_sse/session_manager.py +15 -15
  316. solace_agent_mesh/gateway/http_sse/sse_manager.py +286 -166
  317. solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
  318. solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +41 -1
  319. solace_agent_mesh/services/__init__.py +0 -0
  320. solace_agent_mesh/services/platform/__init__.py +29 -0
  321. solace_agent_mesh/services/platform/alembic/env.py +85 -0
  322. solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
  323. solace_agent_mesh/services/platform/alembic.ini +109 -0
  324. solace_agent_mesh/services/platform/api/__init__.py +3 -0
  325. solace_agent_mesh/services/platform/api/dependencies.py +154 -0
  326. solace_agent_mesh/services/platform/api/main.py +314 -0
  327. solace_agent_mesh/services/platform/api/middleware.py +51 -0
  328. solace_agent_mesh/services/platform/api/routers/__init__.py +33 -0
  329. solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
  330. solace_agent_mesh/services/platform/app.py +215 -0
  331. solace_agent_mesh/services/platform/component.py +777 -0
  332. solace_agent_mesh/shared/__init__.py +14 -0
  333. solace_agent_mesh/shared/api/__init__.py +42 -0
  334. solace_agent_mesh/shared/auth/__init__.py +26 -0
  335. solace_agent_mesh/shared/auth/dependencies.py +204 -0
  336. solace_agent_mesh/shared/auth/middleware.py +347 -0
  337. solace_agent_mesh/shared/database/__init__.py +20 -0
  338. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
  339. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
  340. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
  341. solace_agent_mesh/shared/exceptions/__init__.py +36 -0
  342. solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +19 -5
  343. solace_agent_mesh/shared/utils/__init__.py +21 -0
  344. solace_agent_mesh/templates/logging_config_template.yaml +48 -0
  345. solace_agent_mesh/templates/main_orchestrator.yaml +12 -1
  346. solace_agent_mesh/templates/platform.yaml +49 -0
  347. solace_agent_mesh/templates/plugin_readme_template.md +3 -25
  348. solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
  349. solace_agent_mesh/templates/proxy_template.yaml +62 -0
  350. solace_agent_mesh/templates/webui.yaml +148 -6
  351. solace_agent_mesh/tools/web_search/__init__.py +18 -0
  352. solace_agent_mesh/tools/web_search/base.py +84 -0
  353. solace_agent_mesh/tools/web_search/google_search.py +247 -0
  354. solace_agent_mesh/tools/web_search/models.py +99 -0
  355. {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +31 -12
  356. solace_agent_mesh-1.13.2.dist-info/RECORD +591 -0
  357. {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
  358. solace_agent_mesh/agent/adk/adk_llm.txt +0 -232
  359. solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
  360. solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
  361. solace_agent_mesh/agent/adk/models/models_llm.txt +0 -142
  362. solace_agent_mesh/agent/agent_llm.txt +0 -378
  363. solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
  364. solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
  365. solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
  366. solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
  367. solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
  368. solace_agent_mesh/agent/testing/testing_llm.txt +0 -57
  369. solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
  370. solace_agent_mesh/agent/tools/tools_llm.txt +0 -263
  371. solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -274
  372. solace_agent_mesh/agent/utils/utils_llm.txt +0 -138
  373. solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
  374. solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +0 -1
  375. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
  376. solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +0 -1
  377. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
  378. solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
  379. solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +0 -1
  380. solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +0 -1
  381. solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +0 -1
  382. solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
  383. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +0 -1
  384. solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +0 -1
  385. solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +0 -1
  386. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +0 -1
  387. solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
  388. solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +0 -1
  389. solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +0 -1
  390. solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +0 -1
  391. solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +0 -1
  392. solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +0 -1
  393. solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +0 -1
  394. solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +0 -1
  395. solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +0 -1
  396. solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e6dd091.js +0 -1
  397. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
  398. solace_agent_mesh/assets/docs/assets/js/da0b5bad.d08a9466.js +0 -1
  399. solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +0 -1
  400. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +0 -1
  401. solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +0 -1
  402. solace_agent_mesh/assets/docs/assets/js/e3d9abda.6b9493d0.js +0 -1
  403. solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +0 -1
  404. solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +0 -1
  405. solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +0 -1
  406. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +0 -1
  407. solace_agent_mesh/assets/docs/assets/js/main.b12eac43.js +0 -2
  408. solace_agent_mesh/assets/docs/assets/js/runtime~main.e268214e.js +0 -1
  409. solace_agent_mesh/assets/docs/lunr-index-1761248203150.json +0 -1
  410. solace_agent_mesh/assets/docs/search-doc-1761248203150.json +0 -1
  411. solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
  412. solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
  413. solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
  414. solace_agent_mesh/client/webui/frontend/static/assets/client-CaY59VuC.js +0 -25
  415. solace_agent_mesh/client/webui/frontend/static/assets/main-B32noGmR.js +0 -342
  416. solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +0 -1
  417. solace_agent_mesh/client/webui/frontend/static/assets/vendor-BEmvJSYz.js +0 -405
  418. solace_agent_mesh/common/a2a/a2a_llm.txt +0 -182
  419. solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
  420. solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -407
  421. solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
  422. solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -313
  423. solace_agent_mesh/common/common_llm.txt +0 -251
  424. solace_agent_mesh/common/common_llm_detail.txt +0 -2562
  425. solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
  426. solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
  427. solace_agent_mesh/common/sac/sac_llm.txt +0 -71
  428. solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
  429. solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
  430. solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
  431. solace_agent_mesh/common/services/providers/providers_llm.txt +0 -80
  432. solace_agent_mesh/common/services/services_llm.txt +0 -363
  433. solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
  434. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
  435. solace_agent_mesh/common/utils/utils_llm.txt +0 -336
  436. solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
  437. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +0 -98
  438. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-61038fc6.js +0 -1
  439. solace_agent_mesh/config_portal/frontend/static/client/assets/root-BWvk5-gF.js +0 -10
  440. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +0 -1
  441. solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
  442. solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
  443. solace_agent_mesh/gateway/base/base_llm.txt +0 -224
  444. solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
  445. solace_agent_mesh/gateway/gateway_llm.txt +0 -373
  446. solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
  447. solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -295
  448. solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -155
  449. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
  450. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
  451. solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
  452. solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -263
  453. solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -266
  454. solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -340
  455. solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -346
  456. solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -83
  457. solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -107
  458. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -314
  459. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -297
  460. solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
  461. solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -285
  462. solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
  463. solace_agent_mesh/llm.txt +0 -228
  464. solace_agent_mesh/llm_detail.txt +0 -2835
  465. solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
  466. solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
  467. solace_agent_mesh/templates/logging_config_template.ini +0 -45
  468. solace_agent_mesh/templates/templates_llm.txt +0 -147
  469. solace_agent_mesh-1.6.1.dist-info/RECORD +0 -525
  470. /solace_agent_mesh/assets/docs/assets/js/{main.b12eac43.js.LICENSE.txt → main.d634009f.js.LICENSE.txt} +0 -0
  471. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
  472. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
  473. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
  474. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
  475. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
  476. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
  477. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
  478. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
  479. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
  480. {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
  481. {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
@@ -2,79 +2,87 @@
2
2
  Custom Solace AI Connector Component to Host Google ADK Agents via A2A Protocol.
3
3
  """
4
4
 
5
- import logging
6
- from typing import Any, Dict, Optional, Union, Callable, List, Tuple, TYPE_CHECKING
7
5
  import asyncio
8
- import functools
9
- import threading
10
6
  import concurrent.futures
11
7
  import fnmatch
12
- import time
8
+ import functools
9
+ import inspect
13
10
  import json
14
- from solace_ai_connector.common.message import (
15
- Message as SolaceMessage,
16
- )
17
- from solace_ai_connector.common.event import Event, EventType
11
+ import logging
12
+ import threading
13
+ import time
14
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
15
+
16
+ from litellm.exceptions import BadRequestError
17
+
18
+ from ...common.error_handlers import get_error_message
18
19
 
19
- from solace_ai_connector.common.utils import import_module
20
- import inspect
21
- from pydantic import BaseModel, ValidationError
22
- from google.adk.agents.invocation_context import (
23
- LlmCallsLimitExceededError,
24
- )
25
- from google.adk.agents import RunConfig
26
- from google.adk.agents.run_config import StreamingMode
27
- from google.adk.sessions import BaseSessionService
28
- from google.adk.artifacts import BaseArtifactService
29
- from google.adk.memory import BaseMemoryService
30
- from google.adk.agents import LlmAgent
31
- from google.adk.runners import Runner
32
- from google.adk.models import LlmResponse
33
- from google.adk.agents.readonly_context import ReadonlyContext
34
- from google.adk.events import Event as ADKEvent
35
- from google.adk.agents.callback_context import CallbackContext
36
- from google.adk.models.llm_request import LlmRequest
37
- from google.genai import types as adk_types
38
- from google.adk.tools.mcp_tool import MCPToolset
39
20
  from a2a.types import (
40
21
  AgentCard,
41
- Artifact as A2AArtifact,
42
- Message as A2AMessage,
43
22
  MessageSendParams,
44
23
  SendMessageRequest,
45
24
  TaskState,
46
25
  TaskStatus,
47
26
  TaskStatusUpdateEvent,
48
27
  )
49
- from ...common import a2a
50
- from ...common.data_parts import AgentProgressUpdateData
51
- from ...common.a2a.translation import format_and_route_adk_event
52
- from ...agent.utils.config_parser import resolve_instruction_provider
28
+ from a2a.types import Artifact as A2AArtifact
29
+ from a2a.types import Message as A2AMessage
30
+ from google.adk.agents import LlmAgent, RunConfig
31
+ from google.adk.agents.callback_context import CallbackContext
32
+ from google.adk.agents.invocation_context import LlmCallsLimitExceededError
33
+ from google.adk.agents.readonly_context import ReadonlyContext
34
+ from google.adk.agents.run_config import StreamingMode
35
+ from google.adk.artifacts import BaseArtifactService
36
+ from google.adk.auth.credential_service.base_credential_service import (
37
+ BaseCredentialService,
38
+ )
39
+ from google.adk.events import Event as ADKEvent
40
+ from google.adk.memory import BaseMemoryService
41
+ from google.adk.models import LlmResponse
42
+ from google.adk.models.llm_request import LlmRequest
43
+ from google.adk.runners import Runner
44
+ from google.adk.sessions import BaseSessionService
45
+ from google.adk.tools.mcp_tool import MCPToolset
46
+ from google.adk.tools.openapi_tool import OpenAPIToolset
47
+ from google.genai import types as adk_types
48
+ from pydantic import BaseModel, ValidationError
49
+ from solace_ai_connector.common.event import Event, EventType
50
+ from solace_ai_connector.common.message import Message as SolaceMessage
51
+ from solace_ai_connector.common.utils import import_module
52
+
53
+ from ...agent.adk.runner import TaskCancelledError, run_adk_async_task_thread_wrapper
53
54
  from ...agent.adk.services import (
54
- initialize_session_service,
55
55
  initialize_artifact_service,
56
+ initialize_credential_service,
56
57
  initialize_memory_service,
58
+ initialize_session_service,
57
59
  )
58
60
  from ...agent.adk.setup import (
59
- load_adk_tools,
60
61
  initialize_adk_agent,
61
62
  initialize_adk_runner,
63
+ load_adk_tools,
62
64
  )
63
- from ...agent.protocol.event_handlers import (
64
- process_event,
65
- publish_agent_card,
66
- )
67
- from ...agent.adk.runner import run_adk_async_task_thread_wrapper, TaskCancelledError
65
+ from ...agent.protocol.event_handlers import process_event, publish_agent_card
68
66
  from ...agent.tools.peer_agent_tool import (
69
67
  CORRELATION_DATA_PREFIX,
70
- PeerAgentTool,
71
68
  PEER_TOOL_PREFIX,
69
+ PeerAgentTool,
72
70
  )
73
- from ...common.middleware.registry import MiddlewareRegistry
74
- from ...common.constants import DEFAULT_COMMUNICATION_TIMEOUT, HEALTH_CHECK_TTL_SECONDS, HEALTH_CHECK_INTERVAL_SECONDS
75
71
  from ...agent.tools.registry import tool_registry
76
- from ...common.sac.sam_component_base import SamComponentBase
72
+ from ...agent.utils.config_parser import resolve_instruction_provider
73
+ from ...common import a2a
74
+ from ...common.a2a.translation import format_and_route_adk_event
77
75
  from ...common.agent_registry import AgentRegistry
76
+ from ...common.constants import (
77
+ DEFAULT_COMMUNICATION_TIMEOUT,
78
+ HEALTH_CHECK_INTERVAL_SECONDS,
79
+ HEALTH_CHECK_TTL_SECONDS,
80
+ )
81
+ from ...common.a2a.types import ArtifactInfo
82
+ from ...common.data_parts import AgentProgressUpdateData, ArtifactSavedData
83
+ from ...common.middleware.registry import MiddlewareRegistry
84
+ from ...common.sac.sam_component_base import SamComponentBase
85
+ from ...common.utils.rbac_utils import validate_agent_access
78
86
 
79
87
  log = logging.getLogger(__name__)
80
88
 
@@ -128,8 +136,12 @@ 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 A2A ADK Host Component...", self.log_identifier)
132
-
139
+ log.info(
140
+ "%s Initializing agent: %s (A2A ADK Host Component)...",
141
+ self.log_identifier,
142
+ self.agent_name,
143
+ )
144
+
133
145
  # Initialize the agent registry for health tracking
134
146
  self.agent_registry = AgentRegistry()
135
147
  try:
@@ -226,7 +238,6 @@ class SamAgentComponent(SamComponentBase):
226
238
  "max_message_size_bytes", 10_000_000
227
239
  )
228
240
 
229
- log.info("%s Configuration retrieved successfully.", self.log_identifier)
230
241
  except Exception as e:
231
242
  log.error(
232
243
  "%s Failed to retrieve configuration via get_config: %s",
@@ -237,6 +248,7 @@ class SamAgentComponent(SamComponentBase):
237
248
  self.session_service: BaseSessionService = None
238
249
  self.artifact_service: BaseArtifactService = None
239
250
  self.memory_service: BaseMemoryService = None
251
+ self.credential_service: Optional[BaseCredentialService] = None
240
252
  self.adk_agent: LlmAgent = None
241
253
  self.runner: Runner = None
242
254
  self.agent_card_tool_manifest: List[Dict[str, Any]] = []
@@ -265,9 +277,10 @@ class SamAgentComponent(SamComponentBase):
265
277
  self.session_service = initialize_session_service(self)
266
278
  self.artifact_service = initialize_artifact_service(self)
267
279
  self.memory_service = initialize_memory_service(self)
280
+ self.credential_service = initialize_credential_service(self)
268
281
 
269
282
  log.info(
270
- "%s Synchronous ADK services initialized.", self.log_identifier
283
+ "%s Initialized Synchronous ADK services.", self.log_identifier
271
284
  )
272
285
  except Exception as service_err:
273
286
  log.exception(
@@ -279,6 +292,18 @@ class SamAgentComponent(SamComponentBase):
279
292
  f"Failed to initialize synchronous ADK services: {service_err}"
280
293
  ) from service_err
281
294
 
295
+ # initialize enterprise features if available
296
+ try:
297
+ from solace_agent_mesh_enterprise.init_enterprise_component import (
298
+ init_enterprise_component_features,
299
+ )
300
+
301
+ init_enterprise_component_features(self)
302
+ except ImportError:
303
+ # Community edition
304
+ # Contact Solace support for enterprise features
305
+ pass
306
+
282
307
  from .app import (
283
308
  AgentInitCleanupConfig,
284
309
  ) # delayed import to avoid circular dependency
@@ -403,30 +428,10 @@ class SamAgentComponent(SamComponentBase):
403
428
  # We still need a future to signal completion from the async thread.
404
429
  self._async_init_future = concurrent.futures.Future()
405
430
 
406
- publish_interval_sec = self.agent_card_publishing_config.get(
407
- "interval_seconds"
408
- )
409
- if publish_interval_sec and publish_interval_sec > 0:
410
- log.info(
411
- "%s Scheduling agent card publishing every %d seconds.",
412
- self.log_identifier,
413
- publish_interval_sec,
414
- )
415
- # Register timer with callback
416
- self.add_timer(
417
- delay_ms=1000,
418
- timer_id=self._card_publish_timer_id,
419
- interval_ms=publish_interval_sec * 1000,
420
- callback=lambda timer_data: publish_agent_card(self),
421
- )
422
- else:
423
- log.warning(
424
- "%s Agent card publishing interval not configured or invalid, card will not be published periodically.",
425
- self.log_identifier,
426
- )
427
-
428
431
  # Set up health check timer if enabled
429
- health_check_interval_seconds = self.agent_discovery_config.get("health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS)
432
+ health_check_interval_seconds = self.agent_discovery_config.get(
433
+ "health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS
434
+ )
430
435
  if health_check_interval_seconds > 0:
431
436
  log.info(
432
437
  "%s Scheduling agent health check every %d seconds.",
@@ -444,9 +449,9 @@ class SamAgentComponent(SamComponentBase):
444
449
  "%s Agent health check interval not configured or invalid, health checks will not run periodically.",
445
450
  self.log_identifier,
446
451
  )
447
-
452
+
448
453
  log.info(
449
- "%s Initialization complete for agent: %s",
454
+ "%s Initialized agent: %s",
450
455
  self.log_identifier,
451
456
  self.agent_name,
452
457
  )
@@ -484,6 +489,16 @@ class SamAgentComponent(SamComponentBase):
484
489
  event = Event(EventType.MESSAGE, message)
485
490
  await process_event(self, event)
486
491
 
492
+ def handle_timer_event(self, timer_data: Dict[str, Any]):
493
+ """Handles timer events for agent card publishing and health checks."""
494
+ log.debug("%s Received timer event: %s", self.log_identifier, timer_data)
495
+ timer_id = timer_data.get("timer_id")
496
+
497
+ if timer_id == self._card_publish_timer_id:
498
+ publish_agent_card(self)
499
+ elif timer_id == self.HEALTH_CHECK_TIMER_ID:
500
+ self._check_agent_health()
501
+
487
502
  async def handle_cache_expiry_event(self, cache_data: Dict[str, Any]):
488
503
  """
489
504
  Handles cache expiry events for peer timeouts by calling the atomic claim helper.
@@ -523,6 +538,83 @@ class SamAgentComponent(SamComponentBase):
523
538
  sub_task_id,
524
539
  )
525
540
 
541
+ async def get_main_task_context(
542
+ self, logical_task_id: str
543
+ ) -> Optional["TaskExecutionContext"]:
544
+ """
545
+ Retrieves the main task context for a given logical task ID.
546
+
547
+ This method is used when the current agent is the target agent for the task.
548
+ It returns the TaskExecutionContext which contains the full task state including
549
+ a2a_context, active_peer_sub_tasks, and other task execution details.
550
+
551
+ Args:
552
+ logical_task_id: The unique logical ID of the task
553
+
554
+ Returns:
555
+ The TaskExecutionContext if the task is active, None otherwise
556
+
557
+ Raises:
558
+ ValueError: If logical_task_id is None or empty
559
+ """
560
+ if not logical_task_id:
561
+ raise ValueError("logical_task_id cannot be None or empty")
562
+
563
+ with self.active_tasks_lock:
564
+ active_task_context = self.active_tasks.get(logical_task_id)
565
+ if active_task_context is None:
566
+ log.warning(
567
+ f"No active task context found for logical_task_id: {logical_task_id}"
568
+ )
569
+ return None
570
+
571
+ return active_task_context
572
+
573
+ async def get_all_sub_task_correlation_data_from_logical_task_id(
574
+ self, logical_task_id: str
575
+ ) -> list[dict[str, Any]]:
576
+ """
577
+ Retrieves correlation data for all active peer sub-tasks of a given logical task.
578
+
579
+ This method is used when forwarding requests to other agents in an A2A workflow.
580
+ It returns a list of correlation data dictionaries, each containing information
581
+ about a peer sub-task including peer_task_id, peer_agent_name, and original_task_context.
582
+
583
+ Args:
584
+ logical_task_id: The unique logical ID of the parent task
585
+
586
+ Returns:
587
+ List of correlation data dictionaries for active peer sub-tasks.
588
+ Returns empty list if no active peer sub-tasks exist.
589
+
590
+ Raises:
591
+ ValueError: If logical_task_id is None or empty
592
+ """
593
+ if not logical_task_id:
594
+ raise ValueError("logical_task_id cannot be None or empty")
595
+
596
+ with self.active_tasks_lock:
597
+ active_task_context = self.active_tasks.get(logical_task_id)
598
+ if active_task_context is None:
599
+ log.warning(
600
+ f"No active task context found for logical_task_id: {logical_task_id}"
601
+ )
602
+ return []
603
+
604
+ active_peer_sub_tasks = active_task_context.active_peer_sub_tasks
605
+ if not active_peer_sub_tasks:
606
+ log.debug(
607
+ f"No active peer sub-tasks found for logical_task_id: {logical_task_id}"
608
+ )
609
+ return []
610
+
611
+ results = []
612
+ for sub_task_id, correlation_data in active_peer_sub_tasks.items():
613
+ if sub_task_id is not None and correlation_data is not None:
614
+ results.append(correlation_data)
615
+
616
+ return results
617
+
526
618
  async def _get_correlation_data_for_sub_task(
527
619
  self, sub_task_id: str
528
620
  ) -> Optional[Dict[str, Any]]:
@@ -653,6 +745,14 @@ class SamAgentComponent(SamComponentBase):
653
745
  paused_invocation_id = correlation_data.get("invocation_id")
654
746
  log_retrigger = f"{self.log_identifier}[RetriggerManager:{logical_task_id}]"
655
747
 
748
+ # Clear paused state - task is resuming now
749
+ task_context.set_paused(False)
750
+ log.debug(
751
+ "%s Task %s resuming from paused state with peer responses.",
752
+ log_retrigger,
753
+ logical_task_id,
754
+ )
755
+
656
756
  try:
657
757
  effective_session_id = original_task_context.get("effective_session_id")
658
758
  user_id = original_task_context.get("user_id")
@@ -683,13 +783,8 @@ class SamAgentComponent(SamComponentBase):
683
783
  log_retrigger,
684
784
  len(new_response_parts),
685
785
  )
686
- new_adk_event = ADKEvent(
687
- invocation_id=paused_invocation_id,
688
- author=self.agent_name,
689
- content=adk_types.Content(role="tool", parts=new_response_parts),
690
- )
691
- await self.session_service.append_event(
692
- session=session, event=new_adk_event
786
+ new_tool_response_content = adk_types.Content(
787
+ role="tool", parts=new_response_parts
693
788
  )
694
789
 
695
790
  # Always use SSE streaming mode for the ADK runner, even on re-trigger.
@@ -708,7 +803,12 @@ class SamAgentComponent(SamComponentBase):
708
803
  )
709
804
  try:
710
805
  await run_adk_async_task_thread_wrapper(
711
- 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,
712
812
  )
713
813
  finally:
714
814
  log.info(
@@ -897,12 +997,13 @@ class SamAgentComponent(SamComponentBase):
897
997
  )
898
998
  if peer_tool_instance.name not in llm_request.tools_dict:
899
999
  peer_tools_to_add.append(peer_tool_instance)
900
- description = (
901
- getattr(agent_card, "description", "No description")
902
- 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
903
1004
  )
904
1005
  allowed_peer_descriptions.append(
905
- f"- `peer_{peer_name}`: {description}"
1006
+ f"\n### `peer_{peer_name}`\n{enhanced_desc}"
906
1007
  )
907
1008
  except Exception as e:
908
1009
  log.error(
@@ -915,12 +1016,18 @@ class SamAgentComponent(SamComponentBase):
915
1016
  if allowed_peer_descriptions:
916
1017
  peer_list_str = "\n".join(allowed_peer_descriptions)
917
1018
  instruction_text = (
918
- "You can delegate tasks to other specialized agents if they are better suited.\n"
919
- "Use the `peer_<agent_name>(task_description: str, user_query: str)` tool for delegation. "
920
- "Replace `<agent_name>` with the actual name of the target agent.\n"
921
- "Provide a clear `task_description` for the peer and include the original `user_query` for context.\n"
922
- "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"
923
- "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"
924
1031
  f"{peer_list_str}"
925
1032
  )
926
1033
  callback_context.state["peer_tool_instructions"] = instruction_text
@@ -1434,6 +1541,70 @@ class SamAgentComponent(SamComponentBase):
1434
1541
  )
1435
1542
  return False
1436
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
+
1437
1608
  async def _publish_status_update_with_buffer_flush(
1438
1609
  self,
1439
1610
  status_update_event: TaskStatusUpdateEvent,
@@ -1514,7 +1685,7 @@ class SamAgentComponent(SamComponentBase):
1514
1685
  payload_to_publish, target_topic, a2a_context, user_properties
1515
1686
  )
1516
1687
 
1517
- log.info(
1688
+ log.debug(
1518
1689
  "%s Published %s status update to %s.",
1519
1690
  log_identifier,
1520
1691
  status_type,
@@ -1627,10 +1798,47 @@ class SamAgentComponent(SamComponentBase):
1627
1798
  is_run_based_session = a2a_context.get("is_run_based_session", False)
1628
1799
  is_final_turn_event = not adk_event.partial
1629
1800
 
1801
+ try:
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
+ )
1809
+ if auth_status_update:
1810
+ await self._publish_status_update_with_buffer_flush(
1811
+ auth_status_update,
1812
+ a2a_context,
1813
+ skip_buffer_flush=False,
1814
+ )
1815
+ return
1816
+ except ImportError:
1817
+ pass
1818
+
1630
1819
  if not is_final_turn_event:
1631
1820
  if adk_event.content and adk_event.content.parts:
1632
1821
  for part in adk_event.content.parts:
1633
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
+
1634
1842
  task_context.append_to_streaming_buffer(part.text)
1635
1843
  log.debug(
1636
1844
  "%s Appended text to buffer. New buffer size: %d bytes",
@@ -1655,7 +1863,7 @@ class SamAgentComponent(SamComponentBase):
1655
1863
  )
1656
1864
 
1657
1865
  if buffer_has_content and (batching_disabled or threshold_met):
1658
- log.info(
1866
+ log.debug(
1659
1867
  "%s Partial event triggered buffer flush due to size/batching config.",
1660
1868
  log_id_main,
1661
1869
  )
@@ -1678,7 +1886,7 @@ class SamAgentComponent(SamComponentBase):
1678
1886
  else:
1679
1887
  buffer_content = task_context.get_streaming_buffer_content()
1680
1888
  if buffer_content:
1681
- log.info(
1889
+ log.debug(
1682
1890
  "%s Final event triggered flush of remaining buffer content.",
1683
1891
  log_id_main,
1684
1892
  )
@@ -1712,7 +1920,7 @@ class SamAgentComponent(SamComponentBase):
1712
1920
 
1713
1921
  if a2a_payload and target_topic:
1714
1922
  self._publish_a2a_event(a2a_payload, target_topic, a2a_context)
1715
- log.info(
1923
+ log.debug(
1716
1924
  "%s Published final turn event (e.g., tool call) to %s.",
1717
1925
  log_id_main,
1718
1926
  target_topic,
@@ -1769,7 +1977,7 @@ class SamAgentComponent(SamComponentBase):
1769
1977
  log_id,
1770
1978
  len(signals_found),
1771
1979
  )
1772
- for _signal_index, signal_data_tuple in signals_found:
1980
+ for _signal_index, signal_data_tuple, _placeholder in signals_found:
1773
1981
  if (
1774
1982
  isinstance(signal_data_tuple, tuple)
1775
1983
  and len(signal_data_tuple) == 3
@@ -1785,6 +1993,7 @@ class SamAgentComponent(SamComponentBase):
1785
1993
  await self._publish_agent_status_signal_update(
1786
1994
  status_text, a2a_context
1787
1995
  )
1996
+ resolved_text = resolved_text.replace(_placeholder, "")
1788
1997
 
1789
1998
  return resolved_text, unprocessed_tail
1790
1999
 
@@ -1998,9 +2207,14 @@ class SamAgentComponent(SamComponentBase):
1998
2207
  For STREAMING tasks, it uses the content of the last ADK event.
1999
2208
  """
2000
2209
  logical_task_id = a2a_context.get("logical_task_id")
2001
- original_message: Optional[SolaceMessage] = a2a_context.get(
2002
- "original_solace_message"
2003
- )
2210
+
2211
+ # Retrieve the original Solace message from TaskExecutionContext
2212
+ original_message: Optional[SolaceMessage] = None
2213
+ with self.active_tasks_lock:
2214
+ task_context = self.active_tasks.get(logical_task_id)
2215
+ if task_context:
2216
+ original_message = task_context.get_original_solace_message()
2217
+
2004
2218
  log.info(
2005
2219
  "%s Finalizing task %s successfully.", self.log_identifier, logical_task_id
2006
2220
  )
@@ -2074,6 +2288,19 @@ class SamAgentComponent(SamComponentBase):
2074
2288
  self.log_identifier,
2075
2289
  len(task_context.produced_artifacts),
2076
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
+ )
2077
2304
 
2078
2305
  # Add token usage summary
2079
2306
  if task_context:
@@ -2194,9 +2421,14 @@ class SamAgentComponent(SamComponentBase):
2194
2421
  Called by the background ADK thread wrapper when a task is cancelled.
2195
2422
  """
2196
2423
  logical_task_id = a2a_context.get("logical_task_id")
2197
- original_message: Optional[SolaceMessage] = a2a_context.get(
2198
- "original_solace_message"
2199
- )
2424
+
2425
+ # Retrieve the original Solace message from TaskExecutionContext
2426
+ original_message: Optional[SolaceMessage] = None
2427
+ with self.active_tasks_lock:
2428
+ task_context = self.active_tasks.get(logical_task_id)
2429
+ if task_context:
2430
+ original_message = task_context.get_original_solace_message()
2431
+
2200
2432
  log.info(
2201
2433
  "%s Finalizing task %s as CANCELED.", self.log_identifier, logical_task_id
2202
2434
  )
@@ -2398,9 +2630,14 @@ class SamAgentComponent(SamComponentBase):
2398
2630
  Sends a COMPLETED status with an informative message.
2399
2631
  """
2400
2632
  logical_task_id = a2a_context.get("logical_task_id")
2401
- original_message: Optional[SolaceMessage] = a2a_context.get(
2402
- "original_solace_message"
2403
- )
2633
+
2634
+ # Retrieve the original Solace message from TaskExecutionContext
2635
+ original_message: Optional[SolaceMessage] = None
2636
+ with self.active_tasks_lock:
2637
+ task_context = self.active_tasks.get(logical_task_id)
2638
+ if task_context:
2639
+ original_message = task_context.get_original_solace_message()
2640
+
2404
2641
  log.info(
2405
2642
  "%s Finalizing task %s as COMPLETED (LLM call limit reached).",
2406
2643
  self.log_identifier,
@@ -2477,9 +2714,14 @@ class SamAgentComponent(SamComponentBase):
2477
2714
  Called by the background ADK thread wrapper.
2478
2715
  """
2479
2716
  logical_task_id = a2a_context.get("logical_task_id")
2480
- original_message: Optional[SolaceMessage] = a2a_context.get(
2481
- "original_solace_message"
2482
- )
2717
+
2718
+ # Retrieve the original Solace message from TaskExecutionContext
2719
+ original_message: Optional[SolaceMessage] = None
2720
+ with self.active_tasks_lock:
2721
+ task_context = self.active_tasks.get(logical_task_id)
2722
+ if task_context:
2723
+ original_message = task_context.get_original_solace_message()
2724
+
2483
2725
  log.error(
2484
2726
  "%s Finalizing task %s with error: %s",
2485
2727
  self.log_identifier,
@@ -2496,11 +2738,24 @@ class SamAgentComponent(SamComponentBase):
2496
2738
  peer_reply_topic = a2a_context.get("replyToTopic")
2497
2739
  namespace = self.get_config("namespace")
2498
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
+
2499
2756
  failed_status = a2a.create_task_status(
2500
2757
  state=TaskState.failed,
2501
- message=a2a.create_agent_text_message(
2502
- text="An unexpected error occurred during tool execution. Please try your request again. If the problem persists, contact an administrator."
2503
- ),
2758
+ message=a2a.create_agent_text_message(text=error_message),
2504
2759
  )
2505
2760
 
2506
2761
  final_task = a2a.create_final_task(
@@ -2622,9 +2877,15 @@ class SamAgentComponent(SamComponentBase):
2622
2877
  log_id,
2623
2878
  e,
2624
2879
  )
2625
- original_message: Optional[SolaceMessage] = a2a_context.get(
2626
- "original_solace_message"
2627
- )
2880
+ # Retrieve the original Solace message from TaskExecutionContext for fallback NACK
2881
+ original_message: Optional[SolaceMessage] = None
2882
+ with self.active_tasks_lock:
2883
+ task_context = self.active_tasks.get(logical_task_id)
2884
+ if task_context:
2885
+ original_message = (
2886
+ task_context.get_original_solace_message()
2887
+ )
2888
+
2628
2889
  if original_message:
2629
2890
  try:
2630
2891
  original_message.call_negative_acknowledgements()
@@ -2805,6 +3066,17 @@ class SamAgentComponent(SamComponentBase):
2805
3066
  main_task_id,
2806
3067
  )
2807
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
+
2808
3080
  peer_request_topic = self._get_agent_request_topic(target_agent_name)
2809
3081
 
2810
3082
  # Create a compliant SendMessageRequest
@@ -2825,6 +3097,7 @@ class SamAgentComponent(SamComponentBase):
2825
3097
  "replyTo": reply_to_topic,
2826
3098
  "a2aStatusTopic": status_topic,
2827
3099
  "userId": user_id,
3100
+ "delegating_agent_name": delegating_agent_name,
2828
3101
  }
2829
3102
  if isinstance(user_config, dict):
2830
3103
  user_properties["a2aUserConfig"] = user_config
@@ -2954,6 +3227,31 @@ class SamAgentComponent(SamComponentBase):
2954
3227
  or "No description available.",
2955
3228
  }
2956
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
+ )
2957
3255
  else:
2958
3256
  tool_name = getattr(tool, "name", getattr(tool, "__name__", None))
2959
3257
  if tool_name is not None:
@@ -3011,6 +3309,7 @@ class SamAgentComponent(SamComponentBase):
3011
3309
  "%s _perform_async_init: _async_init_future is None or already done before signaling failure.",
3012
3310
  self.log_identifier,
3013
3311
  )
3312
+ raise e
3014
3313
 
3015
3314
  def cleanup(self):
3016
3315
  """Clean up resources on component shutdown."""
@@ -3139,6 +3438,80 @@ class SamAgentComponent(SamComponentBase):
3139
3438
  """Returns the dedicated asyncio event loop for this component's async tasks."""
3140
3439
  return self._async_loop
3141
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
+
3142
3515
  def set_agent_system_instruction_string(self, instruction_string: str) -> None:
3143
3516
  """
3144
3517
  Sets a static string to be injected into the LLM system prompt.
@@ -3180,79 +3553,93 @@ class SamAgentComponent(SamComponentBase):
3180
3553
  For now, using the agent name, but could be made more robust (e.g., hostname + agent name).
3181
3554
  """
3182
3555
  return self.agent_name
3183
-
3556
+
3184
3557
  def _check_agent_health(self):
3185
3558
  """
3186
3559
  Checks the health of peer agents and de-registers unresponsive ones.
3187
3560
  This is called periodically by the health check timer.
3188
3561
  Uses TTL-based expiration to determine if an agent is unresponsive.
3189
3562
  """
3190
-
3563
+
3191
3564
  log.debug("%s Performing agent health check...", self.log_identifier)
3192
-
3193
- ttl_seconds = self.agent_discovery_config.get("health_check_ttl_seconds", HEALTH_CHECK_TTL_SECONDS)
3194
- health_check_interval = self.agent_discovery_config.get("health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS)
3195
-
3565
+
3566
+ ttl_seconds = self.agent_discovery_config.get(
3567
+ "health_check_ttl_seconds", HEALTH_CHECK_TTL_SECONDS
3568
+ )
3569
+ health_check_interval = self.agent_discovery_config.get(
3570
+ "health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS
3571
+ )
3572
+
3196
3573
  log.debug(
3197
3574
  "%s Health check configuration: interval=%d seconds, TTL=%d seconds",
3198
3575
  self.log_identifier,
3199
3576
  health_check_interval,
3200
- ttl_seconds
3577
+ ttl_seconds,
3201
3578
  )
3202
3579
 
3203
3580
  # Validate configuration values
3204
- if ttl_seconds <= 0 or health_check_interval <= 0 or ttl_seconds < health_check_interval:
3581
+ if (
3582
+ ttl_seconds <= 0
3583
+ or health_check_interval <= 0
3584
+ or ttl_seconds < health_check_interval
3585
+ ):
3205
3586
  log.error(
3206
3587
  "%s agent_health_check_ttl_seconds (%d) and agent_health_check_interval_seconds (%d) must be positive and TTL must be greater than interval.",
3207
3588
  self.log_identifier,
3208
3589
  ttl_seconds,
3209
- health_check_interval
3590
+ health_check_interval,
3591
+ )
3592
+ raise ValueError(
3593
+ f"Invalid health check configuration. agent_health_check_ttl_seconds ({ttl_seconds}) and agent_health_check_interval_seconds ({health_check_interval}) must be positive and TTL must be greater than interval."
3210
3594
  )
3211
- raise ValueError(f"Invalid health check configuration. agent_health_check_ttl_seconds ({ttl_seconds}) and agent_health_check_interval_seconds ({health_check_interval}) must be positive and TTL must be greater than interval.")
3212
-
3595
+
3213
3596
  # Get all agent names from the registry
3214
3597
  agent_names = self.agent_registry.get_agent_names()
3215
3598
  total_agents = len(agent_names)
3216
3599
  agents_to_deregister = []
3217
-
3218
- log.debug("%s Checking health of %d peer agents", self.log_identifier, total_agents)
3219
-
3600
+
3601
+ log.debug(
3602
+ "%s Checking health of %d peer agents", self.log_identifier, total_agents
3603
+ )
3604
+
3220
3605
  for agent_name in agent_names:
3221
3606
  # Skip our own agent
3222
3607
  if agent_name == self.agent_name:
3223
3608
  continue
3224
-
3609
+
3225
3610
  # Check if the agent's TTL has expired
3226
- is_expired, time_since_last_seen = self.agent_registry.check_ttl_expired(agent_name, ttl_seconds)
3227
-
3611
+ is_expired, time_since_last_seen = self.agent_registry.check_ttl_expired(
3612
+ agent_name, ttl_seconds
3613
+ )
3614
+
3228
3615
  if is_expired:
3229
3616
  log.warning(
3230
3617
  "%s Agent '%s' TTL has expired. De-registering. Time since last seen: %d seconds (TTL: %d seconds)",
3231
3618
  self.log_identifier,
3232
3619
  agent_name,
3233
3620
  time_since_last_seen,
3234
- ttl_seconds
3621
+ ttl_seconds,
3235
3622
  )
3236
3623
  agents_to_deregister.append(agent_name)
3237
-
3624
+
3238
3625
  # De-register unresponsive agents
3239
3626
  for agent_name in agents_to_deregister:
3240
3627
  self._deregister_agent(agent_name)
3241
-
3628
+
3242
3629
  log.debug(
3243
3630
  "%s Agent health check completed. Total agents: %d, De-registered: %d",
3244
3631
  self.log_identifier,
3245
3632
  total_agents,
3246
- len(agents_to_deregister)
3633
+ len(agents_to_deregister),
3247
3634
  )
3248
-
3635
+
3249
3636
  def _deregister_agent(self, agent_name: str):
3250
3637
  """
3251
3638
  De-registers an agent from the registry and publishes a de-registration event.
3252
3639
  """
3253
3640
  # Remove from registry
3254
3641
  registry_removed = self.agent_registry.remove_agent(agent_name)
3255
-
3642
+
3256
3643
  # Always remove from peer_agents regardless of registry result
3257
3644
  peer_removed = False
3258
3645
  if agent_name in self.peer_agents:
@@ -3261,18 +3648,18 @@ class SamAgentComponent(SamComponentBase):
3261
3648
  log.info(
3262
3649
  "%s Removed agent '%s' from peer_agents dictionary",
3263
3650
  self.log_identifier,
3264
- agent_name
3651
+ agent_name,
3265
3652
  )
3266
-
3653
+
3267
3654
  # Publish de-registration event if agent was in either data structure
3268
3655
  if registry_removed or peer_removed:
3269
3656
  try:
3270
3657
  # Create a de-registration event topic
3271
3658
  namespace = self.get_config("namespace")
3272
3659
  deregistration_topic = f"{namespace}/a2a/events/agent/deregistered"
3273
-
3660
+
3274
3661
  current_time = time.time()
3275
-
3662
+
3276
3663
  # Create the payload
3277
3664
  deregistration_payload = {
3278
3665
  "event_type": "agent.deregistered",
@@ -3280,28 +3667,27 @@ class SamAgentComponent(SamComponentBase):
3280
3667
  "reason": "health_check_failure",
3281
3668
  "metadata": {
3282
3669
  "timestamp": current_time,
3283
- "deregistered_by": self.agent_name
3284
- }
3670
+ "deregistered_by": self.agent_name,
3671
+ },
3285
3672
  }
3286
-
3673
+
3287
3674
  # Publish the event
3288
3675
  self.publish_a2a_message(
3289
- payload=deregistration_payload,
3290
- topic=deregistration_topic
3676
+ payload=deregistration_payload, topic=deregistration_topic
3291
3677
  )
3292
-
3678
+
3293
3679
  log.info(
3294
3680
  "%s Published de-registration event for agent '%s' to topic '%s'",
3295
3681
  self.log_identifier,
3296
3682
  agent_name,
3297
- deregistration_topic
3683
+ deregistration_topic,
3298
3684
  )
3299
3685
  except Exception as e:
3300
3686
  log.error(
3301
3687
  "%s Failed to publish de-registration event for agent '%s': %s",
3302
3688
  self.log_identifier,
3303
3689
  agent_name,
3304
- e
3690
+ e,
3305
3691
  )
3306
3692
 
3307
3693
  async def _resolve_early_embeds_and_handle_signals(
@@ -3356,11 +3742,12 @@ class SamAgentComponent(SamComponentBase):
3356
3742
  resolver_config = context_for_embeds["config"]
3357
3743
 
3358
3744
  try:
3745
+ from ...common.utils.embeds.constants import EARLY_EMBED_TYPES
3746
+ from ...common.utils.embeds.types import ResolutionMode
3359
3747
  from ...common.utils.embeds.resolver import (
3360
- resolve_embeds_in_string,
3361
3748
  evaluate_embed,
3749
+ resolve_embeds_in_string,
3362
3750
  )
3363
- from ...common.utils.embeds.constants import EARLY_EMBED_TYPES
3364
3751
 
3365
3752
  resolved_text, processed_until_index, signals_found = (
3366
3753
  await resolve_embeds_in_string(
@@ -3368,6 +3755,7 @@ class SamAgentComponent(SamComponentBase):
3368
3755
  context=context_for_embeds,
3369
3756
  resolver_func=evaluate_embed,
3370
3757
  types_to_resolve=EARLY_EMBED_TYPES,
3758
+ resolution_mode=ResolutionMode.TOOL_PARAMETER,
3371
3759
  log_identifier=method_context_log_identifier,
3372
3760
  config=resolver_config,
3373
3761
  )
@@ -3387,16 +3775,62 @@ class SamAgentComponent(SamComponentBase):
3387
3775
  )
3388
3776
  return raw_text, [], ""
3389
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
+
3390
3812
  async def _async_setup_and_run(self) -> None:
3391
3813
  """
3392
3814
  Main async logic for the agent component.
3393
3815
  This is called by the base class's `_run_async_operations`.
3394
3816
  """
3395
- # Call base class to initialize Trust Manager
3396
- 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()
3397
3825
 
3398
- # Perform agent-specific async initialization
3399
- 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
3400
3834
 
3401
3835
  def _pre_async_cleanup(self) -> None:
3402
3836
  """