solace-agent-mesh 1.5.0__py3-none-any.whl → 1.6.0__py3-none-any.whl

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

Potentially problematic release.


This version of solace-agent-mesh might be problematic. Click here for more details.

Files changed (326) hide show
  1. solace_agent_mesh/agent/adk/callbacks.py +14 -17
  2. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +3 -1
  3. solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +2 -1
  4. solace_agent_mesh/agent/adk/mcp_content_processor.py +2 -1
  5. solace_agent_mesh/agent/adk/models/lite_llm.py +123 -8
  6. solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +245 -0
  7. solace_agent_mesh/agent/adk/runner.py +3 -1
  8. solace_agent_mesh/agent/adk/services.py +4 -1
  9. solace_agent_mesh/agent/adk/setup.py +3 -1
  10. solace_agent_mesh/agent/adk/tool_wrapper.py +2 -2
  11. solace_agent_mesh/agent/protocol/event_handlers.py +42 -2
  12. solace_agent_mesh/agent/proxies/__init__.py +0 -0
  13. solace_agent_mesh/agent/proxies/a2a/__init__.py +3 -0
  14. solace_agent_mesh/agent/proxies/a2a/app.py +55 -0
  15. solace_agent_mesh/agent/proxies/a2a/component.py +1115 -0
  16. solace_agent_mesh/agent/proxies/a2a/config.py +140 -0
  17. solace_agent_mesh/agent/proxies/a2a/oauth_token_cache.py +104 -0
  18. solace_agent_mesh/agent/proxies/base/__init__.py +3 -0
  19. solace_agent_mesh/agent/proxies/base/app.py +99 -0
  20. solace_agent_mesh/agent/proxies/base/component.py +619 -0
  21. solace_agent_mesh/agent/proxies/base/config.py +85 -0
  22. solace_agent_mesh/agent/proxies/base/proxy_task_context.py +17 -0
  23. solace_agent_mesh/agent/sac/app.py +12 -4
  24. solace_agent_mesh/agent/sac/component.py +164 -9
  25. solace_agent_mesh/agent/tools/audio_tools.py +127 -9
  26. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +3 -1
  27. solace_agent_mesh/agent/tools/builtin_data_analysis_tools.py +3 -1
  28. solace_agent_mesh/agent/tools/dynamic_tool.py +2 -1
  29. solace_agent_mesh/agent/tools/general_agent_tools.py +2 -1
  30. solace_agent_mesh/agent/tools/image_tools.py +2 -1
  31. solace_agent_mesh/agent/tools/peer_agent_tool.py +2 -1
  32. solace_agent_mesh/agent/tools/registry.py +3 -1
  33. solace_agent_mesh/agent/tools/test_tools.py +2 -1
  34. solace_agent_mesh/agent/tools/web_tools.py +12 -6
  35. solace_agent_mesh/agent/utils/artifact_helpers.py +144 -4
  36. solace_agent_mesh/agent/utils/config_parser.py +3 -1
  37. solace_agent_mesh/assets/docs/404.html +3 -3
  38. solace_agent_mesh/assets/docs/assets/js/{b7006a3a.73a79653.js → 032c2d61.f3d37824.js} +1 -1
  39. solace_agent_mesh/assets/docs/assets/js/0bcf40b7.c019ad46.js +1 -0
  40. solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +1 -0
  41. solace_agent_mesh/assets/docs/assets/js/2131ec11.5c7a1f6e.js +1 -0
  42. solace_agent_mesh/assets/docs/assets/js/{2334.622a6395.js → 2334.1cf50a20.js} +1 -1
  43. solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +1 -0
  44. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +1 -0
  45. solace_agent_mesh/assets/docs/assets/js/341393d4.0fac2613.js +1 -0
  46. solace_agent_mesh/assets/docs/assets/js/{3624.b524e433.js → 3624.0eaa1fd0.js} +1 -1
  47. solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/509e993c.4c7a1a6d.js +1 -0
  51. solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +1 -0
  52. solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +1 -0
  53. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +1 -0
  54. solace_agent_mesh/assets/docs/assets/js/6063ff4c.ef84f702.js +1 -0
  55. solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +1 -0
  56. solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +1 -0
  57. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +1 -0
  59. solace_agent_mesh/assets/docs/assets/js/6fdfefc7.99de744e.js +1 -0
  60. solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +1 -0
  61. solace_agent_mesh/assets/docs/assets/js/722f809d.965da774.js +1 -0
  62. solace_agent_mesh/assets/docs/assets/js/742f027b.46c07808.js +1 -0
  63. solace_agent_mesh/assets/docs/assets/js/77cf947d.48cb18a2.js +1 -0
  64. solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +1 -0
  65. solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +1 -0
  66. solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +1 -0
  67. solace_agent_mesh/assets/docs/assets/js/{8591.d7c16be6.js → 8591.5d015485.js} +2 -2
  68. solace_agent_mesh/assets/docs/assets/js/{8731.49e930c2.js → 8731.6c1dbf0c.js} +1 -1
  69. solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +1 -0
  70. solace_agent_mesh/assets/docs/assets/js/945fb41e.6f4cdffd.js +1 -0
  71. solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +1 -0
  72. solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +1 -0
  73. solace_agent_mesh/assets/docs/assets/js/9e9d0a82.570c057b.js +1 -0
  74. solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e6dd091.js +1 -0
  75. solace_agent_mesh/assets/docs/assets/js/ad71b5ed.af3ecfd1.js +1 -0
  76. solace_agent_mesh/assets/docs/assets/js/c198a0dc.8f31f867.js +1 -0
  77. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +1 -0
  78. solace_agent_mesh/assets/docs/assets/js/ceb2a7a6.5d92d7d0.js +1 -0
  79. solace_agent_mesh/assets/docs/assets/js/da0b5bad.d08a9466.js +1 -0
  80. solace_agent_mesh/assets/docs/assets/js/db924877.e98d12a1.js +1 -0
  81. solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +1 -0
  82. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +1 -0
  83. solace_agent_mesh/assets/docs/assets/js/de5f4c65.e8241890.js +1 -0
  84. solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +1 -0
  85. solace_agent_mesh/assets/docs/assets/js/e3d9abda.2b916f9e.js +1 -0
  86. solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +1 -0
  87. solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +1 -0
  88. solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +1 -0
  89. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +1 -0
  90. solace_agent_mesh/assets/docs/assets/js/main.20feee82.js +2 -0
  91. solace_agent_mesh/assets/docs/assets/js/runtime~main.0d198646.js +1 -0
  92. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +154 -0
  93. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/artifact-management/index.html +7 -7
  94. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/audio-tools/index.html +7 -7
  95. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/data-analysis-tools/index.html +8 -8
  96. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/embeds/index.html +6 -6
  97. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/index.html +11 -11
  98. solace_agent_mesh/assets/docs/docs/documentation/{concepts → components}/cli/index.html +25 -25
  99. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +91 -0
  100. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +29 -0
  101. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +55 -0
  102. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +110 -0
  103. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +262 -0
  104. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +104 -0
  105. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +85 -0
  106. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +25 -0
  107. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +59 -0
  108. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/create-agents/index.html +113 -152
  109. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/create-gateways/index.html +10 -10
  110. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/creating-python-tools/index.html +12 -12
  111. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +54 -0
  112. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +135 -0
  113. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +34 -0
  114. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +55 -0
  115. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/bedrock-agents/index.html +25 -25
  116. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/custom-agent/index.html +13 -13
  117. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/event-mesh-gateway/index.html +12 -12
  118. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/mcp-integration/index.html +10 -10
  119. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/mongodb-integration/index.html +13 -13
  120. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/rag-integration/index.html +13 -13
  121. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/rest-gateway/index.html +10 -10
  122. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +72 -0
  123. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/sql-database/index.html +14 -14
  124. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +33 -0
  125. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +83 -0
  126. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +222 -0
  127. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +161 -0
  128. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +75 -0
  129. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +53 -0
  130. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +35 -100
  131. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +41 -0
  132. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +81 -0
  133. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +25 -0
  134. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +76 -0
  135. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +160 -0
  136. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +142 -0
  137. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +100 -0
  138. solace_agent_mesh/assets/docs/docs/documentation/{Migrations/A2A Upgrade To 0.3.0/a2a-technical-migration-map/index.html → migrations/a2a-upgrade/a2a-technical-migration-map/index.html} +10 -11
  139. solace_agent_mesh/assets/docs/img/solace-logo.png +0 -0
  140. solace_agent_mesh/assets/docs/lunr-index-1761165361160.json +1 -0
  141. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  142. solace_agent_mesh/assets/docs/search-doc-1761165361160.json +1 -0
  143. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  144. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  145. solace_agent_mesh/cli/__init__.py +1 -1
  146. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +2 -69
  147. solace_agent_mesh/cli/commands/eval_cmd.py +11 -49
  148. solace_agent_mesh/cli/commands/init_cmd/__init__.py +0 -5
  149. solace_agent_mesh/cli/commands/init_cmd/env_step.py +10 -12
  150. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +9 -61
  151. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +9 -49
  152. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +1 -2
  153. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-DwrxZE0E.js → authCallback-BTf6dqwp.js} +1 -1
  154. solace_agent_mesh/client/webui/frontend/static/assets/{client-DarGQzyw.js → client-CaY59VuC.js} +1 -1
  155. solace_agent_mesh/client/webui/frontend/static/assets/main-BGTaW0uv.js +342 -0
  156. solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +1 -0
  157. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BKIeiHj_.js → vendor-BEmvJSYz.js} +1 -1
  158. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  159. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  160. solace_agent_mesh/common/a2a/__init__.py +24 -0
  161. solace_agent_mesh/common/a2a/artifact.py +41 -1
  162. solace_agent_mesh/common/a2a/events.py +29 -0
  163. solace_agent_mesh/common/a2a/message.py +68 -0
  164. solace_agent_mesh/common/a2a/protocol.py +76 -3
  165. solace_agent_mesh/common/a2a/translation.py +3 -1
  166. solace_agent_mesh/common/agent_registry.py +83 -3
  167. solace_agent_mesh/common/constants.py +3 -1
  168. solace_agent_mesh/common/middleware/config_resolver.py +3 -1
  169. solace_agent_mesh/common/middleware/registry.py +3 -1
  170. solace_agent_mesh/common/sac/sam_component_base.py +2 -1
  171. solace_agent_mesh/common/sam_events/event_service.py +3 -2
  172. solace_agent_mesh/common/services/employee_service.py +3 -1
  173. solace_agent_mesh/common/services/identity_service.py +2 -1
  174. solace_agent_mesh/common/services/providers/local_file_identity_service.py +2 -1
  175. solace_agent_mesh/common/utils/artifact_utils.py +3 -1
  176. solace_agent_mesh/common/utils/asyncio_macos_fix.py +3 -1
  177. solace_agent_mesh/common/utils/embeds/converter.py +3 -1
  178. solace_agent_mesh/common/utils/embeds/evaluators.py +2 -1
  179. solace_agent_mesh/common/utils/embeds/modifiers.py +3 -2
  180. solace_agent_mesh/common/utils/embeds/resolver.py +2 -1
  181. solace_agent_mesh/common/utils/initializer.py +3 -1
  182. solace_agent_mesh/common/utils/message_utils.py +2 -1
  183. solace_agent_mesh/common/utils/push_notification_auth.py +3 -2
  184. solace_agent_mesh/common/utils/pydantic_utils.py +12 -0
  185. solace_agent_mesh/config_portal/backend/common.py +1 -1
  186. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +98 -0
  187. solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-44d62be6.js → manifest-61038fc6.js} +1 -1
  188. solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
  189. solace_agent_mesh/core_a2a/service.py +2 -2
  190. solace_agent_mesh/evaluation/evaluator.py +128 -104
  191. solace_agent_mesh/evaluation/message_organizer.py +116 -110
  192. solace_agent_mesh/evaluation/report_data_processor.py +84 -86
  193. solace_agent_mesh/evaluation/report_generator.py +73 -79
  194. solace_agent_mesh/evaluation/run.py +421 -235
  195. solace_agent_mesh/evaluation/shared/__init__.py +92 -0
  196. solace_agent_mesh/evaluation/shared/constants.py +47 -0
  197. solace_agent_mesh/evaluation/shared/exceptions.py +50 -0
  198. solace_agent_mesh/evaluation/shared/helpers.py +35 -0
  199. solace_agent_mesh/evaluation/shared/test_case_loader.py +167 -0
  200. solace_agent_mesh/evaluation/shared/test_suite_loader.py +280 -0
  201. solace_agent_mesh/evaluation/subscriber.py +111 -232
  202. solace_agent_mesh/evaluation/summary_builder.py +227 -117
  203. solace_agent_mesh/gateway/base/app.py +3 -2
  204. solace_agent_mesh/gateway/base/component.py +11 -2
  205. solace_agent_mesh/gateway/base/task_context.py +2 -1
  206. solace_agent_mesh/gateway/http_sse/alembic/versions/20251015_add_session_performance_indexes.py +70 -0
  207. solace_agent_mesh/gateway/http_sse/app.py +2 -1
  208. solace_agent_mesh/gateway/http_sse/component.py +102 -3
  209. solace_agent_mesh/gateway/http_sse/components/task_logger_forwarder.py +3 -2
  210. solace_agent_mesh/gateway/http_sse/components/visualization_forwarder_component.py +3 -1
  211. solace_agent_mesh/gateway/http_sse/dependencies.py +7 -5
  212. solace_agent_mesh/gateway/http_sse/main.py +5 -2
  213. solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +12 -13
  214. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +15 -18
  215. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +25 -18
  216. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +30 -26
  217. solace_agent_mesh/gateway/http_sse/repository/task_repository.py +35 -44
  218. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +7 -5
  219. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +97 -205
  220. solace_agent_mesh/gateway/http_sse/routers/auth.py +3 -1
  221. solace_agent_mesh/gateway/http_sse/routers/config.py +3 -2
  222. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +4 -3
  223. solace_agent_mesh/gateway/http_sse/routers/people.py +3 -1
  224. solace_agent_mesh/gateway/http_sse/routers/sessions.py +5 -3
  225. solace_agent_mesh/gateway/http_sse/routers/sse.py +3 -2
  226. solace_agent_mesh/gateway/http_sse/routers/tasks.py +35 -42
  227. solace_agent_mesh/gateway/http_sse/routers/users.py +3 -1
  228. solace_agent_mesh/gateway/http_sse/routers/visualization.py +19 -12
  229. solace_agent_mesh/gateway/http_sse/services/agent_card_service.py +3 -1
  230. solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +6 -5
  231. solace_agent_mesh/gateway/http_sse/services/feedback_service.py +53 -44
  232. solace_agent_mesh/gateway/http_sse/services/people_service.py +2 -2
  233. solace_agent_mesh/gateway/http_sse/services/session_service.py +23 -21
  234. solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +10 -9
  235. solace_agent_mesh/gateway/http_sse/services/task_service.py +3 -2
  236. solace_agent_mesh/gateway/http_sse/session_manager.py +2 -1
  237. solace_agent_mesh/gateway/http_sse/shared/base_repository.py +45 -71
  238. solace_agent_mesh/gateway/http_sse/shared/types.py +0 -18
  239. solace_agent_mesh/gateway/http_sse/sse_event_buffer.py +2 -1
  240. solace_agent_mesh/gateway/http_sse/sse_manager.py +2 -2
  241. solace_agent_mesh/templates/gateway_app_template.py +4 -2
  242. solace_agent_mesh/templates/gateway_component_template.py +3 -1
  243. solace_agent_mesh/templates/gateway_config_template.yaml +0 -5
  244. solace_agent_mesh/templates/logging_config_template.ini +27 -46
  245. solace_agent_mesh/templates/plugin_gateway_config_template.yaml +0 -3
  246. solace_agent_mesh/templates/plugin_tools_template.py +2 -2
  247. solace_agent_mesh/templates/shared_config.yaml +40 -0
  248. {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/METADATA +47 -21
  249. {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/RECORD +254 -225
  250. solace_agent_mesh/assets/docs/assets/images/sac-flows-80d5b603c6aafd33e87945680ce0abf3.png +0 -0
  251. solace_agent_mesh/assets/docs/assets/images/sac_parts_of_a_component-cb3d0424b1d0c17734c5435cca6b4082.png +0 -0
  252. solace_agent_mesh/assets/docs/assets/js/04989206.a248f00c.js +0 -1
  253. solace_agent_mesh/assets/docs/assets/js/0e682baa.d54b8668.js +0 -1
  254. solace_agent_mesh/assets/docs/assets/js/1023fc19.8a8a9309.js +0 -1
  255. solace_agent_mesh/assets/docs/assets/js/1523c6b4.2645ef68.js +0 -1
  256. solace_agent_mesh/assets/docs/assets/js/166ab619.e27886d9.js +0 -1
  257. solace_agent_mesh/assets/docs/assets/js/1c6e87d2.e056b7e0.js +0 -1
  258. solace_agent_mesh/assets/docs/assets/js/21ceee5f.3bf39250.js +0 -1
  259. solace_agent_mesh/assets/docs/assets/js/2a9cab12.2afaee76.js +0 -1
  260. solace_agent_mesh/assets/docs/assets/js/332e10b5.f7629851.js +0 -1
  261. solace_agent_mesh/assets/docs/assets/js/3d406171.5560fdf9.js +0 -1
  262. solace_agent_mesh/assets/docs/assets/js/42b3f8d8.508ae8db.js +0 -1
  263. solace_agent_mesh/assets/docs/assets/js/442a8107.b5c2532a.js +0 -1
  264. solace_agent_mesh/assets/docs/assets/js/453a82a6.3c6bb61d.js +0 -1
  265. solace_agent_mesh/assets/docs/assets/js/483cef9a.bf9398af.js +0 -1
  266. solace_agent_mesh/assets/docs/assets/js/4c2787c2.c1290a40.js +0 -1
  267. solace_agent_mesh/assets/docs/assets/js/55f47984.bcd00a86.js +0 -1
  268. solace_agent_mesh/assets/docs/assets/js/5b4258a4.fdfd2325.js +0 -1
  269. solace_agent_mesh/assets/docs/assets/js/664b740a.ba305a89.js +0 -1
  270. solace_agent_mesh/assets/docs/assets/js/75384d09.c19e8b51.js +0 -1
  271. solace_agent_mesh/assets/docs/assets/js/768e31b0.9abcdc48.js +0 -1
  272. solace_agent_mesh/assets/docs/assets/js/85387663.be2bc838.js +0 -1
  273. solace_agent_mesh/assets/docs/assets/js/945fb41e.16e00776.js +0 -1
  274. solace_agent_mesh/assets/docs/assets/js/9a09e75d.92de8cf5.js +0 -1
  275. solace_agent_mesh/assets/docs/assets/js/9eff14a2.d62aad71.js +0 -1
  276. solace_agent_mesh/assets/docs/assets/js/a12a4955.25fbed32.js +0 -1
  277. solace_agent_mesh/assets/docs/assets/js/a3a92b25.af35e313.js +0 -1
  278. solace_agent_mesh/assets/docs/assets/js/aba87c2f.4ddf32f2.js +0 -1
  279. solace_agent_mesh/assets/docs/assets/js/ae0e903d.5fe5203f.js +0 -1
  280. solace_agent_mesh/assets/docs/assets/js/ae4415af.16cc58d3.js +0 -1
  281. solace_agent_mesh/assets/docs/assets/js/bac0be12.17de4316.js +0 -1
  282. solace_agent_mesh/assets/docs/assets/js/c2c06897.87cb1f47.js +0 -1
  283. solace_agent_mesh/assets/docs/assets/js/c835a94d.ce21f0bf.js +0 -1
  284. solace_agent_mesh/assets/docs/assets/js/cc969b05.feef7dcc.js +0 -1
  285. solace_agent_mesh/assets/docs/assets/js/cd3d4052.a19e7d78.js +0 -1
  286. solace_agent_mesh/assets/docs/assets/js/ced92a13.fb92e7ca.js +0 -1
  287. solace_agent_mesh/assets/docs/assets/js/cee5d587.47904f5e.js +0 -1
  288. solace_agent_mesh/assets/docs/assets/js/d6a81ee7.829198f1.js +0 -1
  289. solace_agent_mesh/assets/docs/assets/js/f284c35a.ed8dd236.js +0 -1
  290. solace_agent_mesh/assets/docs/assets/js/f897a61a.126663fe.js +0 -1
  291. solace_agent_mesh/assets/docs/assets/js/fbfa3e75.e144b16c.js +0 -1
  292. solace_agent_mesh/assets/docs/assets/js/main.0c149855.js +0 -2
  293. solace_agent_mesh/assets/docs/assets/js/runtime~main.c66557e4.js +0 -1
  294. solace_agent_mesh/assets/docs/docs/documentation/Enterprise/installation/index.html +0 -46
  295. solace_agent_mesh/assets/docs/docs/documentation/Enterprise/rbac-setup-guilde/index.html +0 -201
  296. solace_agent_mesh/assets/docs/docs/documentation/Enterprise/single-sign-on/index.html +0 -29
  297. solace_agent_mesh/assets/docs/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0/index.html +0 -105
  298. solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +0 -144
  299. solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +0 -91
  300. solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +0 -91
  301. solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +0 -55
  302. solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +0 -111
  303. solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +0 -77
  304. solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +0 -48
  305. solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +0 -54
  306. solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +0 -45
  307. solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/index.html +0 -74
  308. solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/litellm_models/index.html +0 -49
  309. solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +0 -76
  310. solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +0 -73
  311. solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +0 -72
  312. solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +0 -54
  313. solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +0 -69
  314. solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +0 -59
  315. solace_agent_mesh/assets/docs/lunr-index-1760032255022.json +0 -1
  316. solace_agent_mesh/assets/docs/search-doc-1760032255022.json +0 -1
  317. solace_agent_mesh/client/webui/frontend/static/assets/main-CZbpmwfA.css +0 -1
  318. solace_agent_mesh/client/webui/frontend/static/assets/main-C__uuUkB.js +0 -339
  319. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-BNuqpWDc.js +0 -98
  320. solace_agent_mesh/evaluation/config_loader.py +0 -657
  321. solace_agent_mesh/evaluation/test_case_loader.py +0 -714
  322. /solace_agent_mesh/assets/docs/assets/js/{8591.d7c16be6.js.LICENSE.txt → 8591.5d015485.js.LICENSE.txt} +0 -0
  323. /solace_agent_mesh/assets/docs/assets/js/{main.0c149855.js.LICENSE.txt → main.20feee82.js.LICENSE.txt} +0 -0
  324. {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/WHEEL +0 -0
  325. {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/entry_points.txt +0 -0
  326. {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,85 @@
1
+ """
2
+ Pydantic configuration models for proxy applications.
3
+ """
4
+
5
+ from typing import List, Literal, Optional
6
+
7
+ from pydantic import Field, model_validator
8
+
9
+ from ....common.utils.pydantic_utils import SamConfigBase
10
+
11
+
12
+ class ArtifactServiceConfig(SamConfigBase):
13
+ """Configuration for the shared Artifact Service."""
14
+
15
+ type: str = Field(
16
+ ..., description="Service type (e.g., 'memory', 'gcs', 'filesystem')."
17
+ )
18
+ base_path: Optional[str] = Field(
19
+ default=None,
20
+ description="Base directory path (required for type 'filesystem').",
21
+ )
22
+ bucket_name: Optional[str] = Field(
23
+ default=None, description="GCS bucket name (required for type 'gcs')."
24
+ )
25
+ artifact_scope: Literal["namespace", "app", "custom"] = Field(
26
+ default="namespace", description="Process-wide scope for all artifact services."
27
+ )
28
+ artifact_scope_value: Optional[str] = Field(
29
+ default=None,
30
+ description="Custom identifier for artifact scope (required if artifact_scope is 'custom').",
31
+ )
32
+
33
+ @model_validator(mode="after")
34
+ def check_artifact_scope(self) -> "ArtifactServiceConfig":
35
+ if self.artifact_scope == "custom" and not self.artifact_scope_value:
36
+ raise ValueError(
37
+ "'artifact_scope_value' is required when 'artifact_scope' is 'custom'."
38
+ )
39
+ if self.artifact_scope != "custom" and self.artifact_scope_value:
40
+ from solace_ai_connector.common.log import log
41
+ log.warning(
42
+ "Configuration Warning: 'artifact_scope_value' is ignored when 'artifact_scope' is not 'custom'."
43
+ )
44
+ return self
45
+
46
+
47
+ class ProxiedAgentConfig(SamConfigBase):
48
+ """Base configuration for a proxied agent."""
49
+
50
+ name: str = Field(
51
+ ...,
52
+ description="The name the agent will have on the Solace mesh.",
53
+ )
54
+ request_timeout_seconds: Optional[int] = Field(
55
+ default=None,
56
+ description="Optional timeout override for this specific agent.",
57
+ )
58
+
59
+
60
+ class BaseProxyAppConfig(SamConfigBase):
61
+ """Base configuration for all proxy applications."""
62
+
63
+ namespace: str = Field(
64
+ ...,
65
+ description="Absolute topic prefix for A2A communication (e.g., 'myorg/dev').",
66
+ )
67
+ proxied_agents: List[ProxiedAgentConfig] = Field(
68
+ ...,
69
+ min_length=1,
70
+ description="A list of downstream agents to be proxied.",
71
+ )
72
+ artifact_service: ArtifactServiceConfig = Field(
73
+ default_factory=lambda: ArtifactServiceConfig(type="memory"),
74
+ description="Configuration for the shared Artifact Service.",
75
+ )
76
+ discovery_interval_seconds: int = Field(
77
+ default=60,
78
+ ge=0,
79
+ description="Interval (seconds) to re-fetch agent cards. <= 0 disables periodic discovery.",
80
+ )
81
+ default_request_timeout_seconds: int = Field(
82
+ default=300,
83
+ gt=0,
84
+ description="Default timeout in seconds for requests to downstream agents.",
85
+ )
@@ -0,0 +1,17 @@
1
+ """
2
+ Encapsulates the runtime state for a single, in-flight proxied agent task.
3
+ """
4
+
5
+ from typing import Any, Dict
6
+ from dataclasses import dataclass
7
+
8
+
9
+ @dataclass
10
+ class ProxyTaskContext:
11
+ """
12
+ A class to hold all runtime state and control mechanisms for a single proxied agent task.
13
+ This object is created when a task is initiated and destroyed when it completes.
14
+ """
15
+
16
+ task_id: str
17
+ a2a_context: Dict[str, Any]
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  import sys
2
3
  import os
3
4
 
@@ -7,7 +8,6 @@ sys.path.insert(
7
8
 
8
9
  from common.utils.asyncio_macos_fix import ensure_asyncio_compatibility
9
10
  from .patch_adk import patch_adk
10
- from solace_ai_connector.common.log import log
11
11
 
12
12
  ensure_asyncio_compatibility()
13
13
  patch_adk()
@@ -23,12 +23,14 @@ from ...common.a2a import (
23
23
  get_agent_status_subscription_topic,
24
24
  get_sam_events_subscription_topic,
25
25
  )
26
- from ...common.constants import DEFAULT_COMMUNICATION_TIMEOUT, TEXT_ARTIFACT_CONTEXT_MAX_LENGTH_CAPACITY, TEXT_ARTIFACT_CONTEXT_DEFAULT_LENGTH
26
+ from ...common.constants import DEFAULT_COMMUNICATION_TIMEOUT, TEXT_ARTIFACT_CONTEXT_MAX_LENGTH_CAPACITY, TEXT_ARTIFACT_CONTEXT_DEFAULT_LENGTH, HEALTH_CHECK_TTL_SECONDS, HEALTH_CHECK_INTERVAL_SECONDS
27
27
  from ...agent.sac.component import SamAgentComponent
28
28
  from ...agent.utils.artifact_helpers import DEFAULT_SCHEMA_MAX_KEYS
29
29
  from ...common.utils.pydantic_utils import SamConfigBase
30
30
  from ..tools.tool_config_types import AnyToolConfig
31
31
 
32
+ log = logging.getLogger(__name__)
33
+
32
34
  info = {
33
35
  "class_name": "SamAgentApp",
34
36
  "description": "Custom App class for SAM Agent Host with namespace prefixing and automatic subscription generation.",
@@ -77,6 +79,12 @@ class AgentDiscoveryConfig(SamConfigBase):
77
79
  enabled: bool = Field(
78
80
  default=True, description="Enable discovery and instruction injection."
79
81
  )
82
+ health_check_ttl_seconds: int = Field(
83
+ default=HEALTH_CHECK_TTL_SECONDS, description="Time-to-live in seconds after which an unresponsive agent is de-registered."
84
+ )
85
+ health_check_interval_seconds: int = Field(
86
+ default=HEALTH_CHECK_INTERVAL_SECONDS, description="Interval in seconds between health checks."
87
+ )
80
88
 
81
89
 
82
90
  class InterAgentCommunicationConfig(SamConfigBase):
@@ -450,8 +458,8 @@ class SamAgentApp(App):
450
458
  broker_config["queue_name"] = generated_queue_name
451
459
  log.debug("Injected generated broker.queue_name: %s", generated_queue_name)
452
460
 
453
- broker_config["temporary_queue"] = True
454
- log.debug("Set broker_config.temporary_queue = True")
461
+ broker_config["temporary_queue"] = app_info.get("broker", {}).get("temporary_queue", True)
462
+ log.debug("Set broker_config.temporary_queue = %s", broker_config["temporary_queue"])
455
463
 
456
464
  super().__init__(app_info, **kwargs)
457
465
  log.debug("%s Agent initialization complete.", agent_name)
@@ -2,21 +2,20 @@
2
2
  Custom Solace AI Connector Component to Host Google ADK Agents via A2A Protocol.
3
3
  """
4
4
 
5
+ import logging
5
6
  from typing import Any, Dict, Optional, Union, Callable, List, Tuple, TYPE_CHECKING
6
7
  import asyncio
7
8
  import functools
8
9
  import threading
9
10
  import concurrent.futures
10
- import uuid
11
11
  import fnmatch
12
- import base64
13
- from datetime import datetime, timezone
12
+ import time
14
13
  import json
15
14
  from solace_ai_connector.common.message import (
16
15
  Message as SolaceMessage,
17
16
  )
18
- from solace_ai_connector.common.log import log
19
17
  from solace_ai_connector.common.event import Event, EventType
18
+
20
19
  from solace_ai_connector.common.utils import import_module
21
20
  import inspect
22
21
  from pydantic import BaseModel, ValidationError
@@ -72,9 +71,12 @@ from ...agent.tools.peer_agent_tool import (
72
71
  PEER_TOOL_PREFIX,
73
72
  )
74
73
  from ...common.middleware.registry import MiddlewareRegistry
75
- from ...common.constants import DEFAULT_COMMUNICATION_TIMEOUT
74
+ from ...common.constants import DEFAULT_COMMUNICATION_TIMEOUT, HEALTH_CHECK_TTL_SECONDS, HEALTH_CHECK_INTERVAL_SECONDS
76
75
  from ...agent.tools.registry import tool_registry
77
76
  from ...common.sac.sam_component_base import SamComponentBase
77
+ from ...common.agent_registry import AgentRegistry
78
+
79
+ log = logging.getLogger(__name__)
78
80
 
79
81
  if TYPE_CHECKING:
80
82
  from .app import AgentInitCleanupConfig
@@ -110,6 +112,7 @@ class SamAgentComponent(SamComponentBase):
110
112
 
111
113
  CORRELATION_DATA_PREFIX = CORRELATION_DATA_PREFIX
112
114
  HOST_COMPONENT_VERSION = "1.0.0-alpha"
115
+ HEALTH_CHECK_TIMER_ID = "agent_health_check"
113
116
 
114
117
  def __init__(self, **kwargs):
115
118
  """
@@ -126,6 +129,9 @@ class SamAgentComponent(SamComponentBase):
126
129
  super().__init__(info, **kwargs)
127
130
  self.agent_name = self.get_config("agent_name")
128
131
  log.info("%s Initializing A2A ADK Host Component...", self.log_identifier)
132
+
133
+ # Initialize the agent registry for health tracking
134
+ self.agent_registry = AgentRegistry()
129
135
  try:
130
136
  self.namespace = self.get_config("namespace")
131
137
  if not self.namespace:
@@ -234,7 +240,7 @@ class SamAgentComponent(SamComponentBase):
234
240
  self.adk_agent: LlmAgent = None
235
241
  self.runner: Runner = None
236
242
  self.agent_card_tool_manifest: List[Dict[str, Any]] = []
237
- self.peer_agents: Dict[str, Any] = {}
243
+ self.peer_agents: Dict[str, Any] = {} # Keep for backward compatibility
238
244
  self._card_publish_timer_id: str = f"publish_card_{self.agent_name}"
239
245
  self._async_init_future = None
240
246
  self.peer_response_queues: Dict[str, asyncio.Queue] = {}
@@ -411,6 +417,26 @@ class SamAgentComponent(SamComponentBase):
411
417
  "%s Agent card publishing interval not configured or invalid, card will not be published periodically.",
412
418
  self.log_identifier,
413
419
  )
420
+
421
+ # Set up health check timer if enabled
422
+ health_check_interval_seconds = self.agent_discovery_config.get("health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS)
423
+ if health_check_interval_seconds > 0:
424
+ log.info(
425
+ "%s Scheduling agent health check every %d seconds.",
426
+ self.log_identifier,
427
+ health_check_interval_seconds,
428
+ )
429
+ self.add_timer(
430
+ delay_ms=health_check_interval_seconds * 1000,
431
+ timer_id=self.HEALTH_CHECK_TIMER_ID,
432
+ interval_ms=health_check_interval_seconds * 1000,
433
+ )
434
+ else:
435
+ log.warning(
436
+ "%s Agent health check interval not configured or invalid, health checks will not run periodically.",
437
+ self.log_identifier,
438
+ )
439
+
414
440
  log.info(
415
441
  "%s Initialization complete for agent: %s",
416
442
  self.log_identifier,
@@ -485,10 +511,14 @@ class SamAgentComponent(SamComponentBase):
485
511
  )
486
512
 
487
513
  def handle_timer_event(self, timer_data: Dict[str, Any]):
488
- """Handles timer events, specifically for agent card publishing."""
514
+ """Handles timer events for agent card publishing and health checks."""
489
515
  log.debug("%s Received timer event: %s", self.log_identifier, timer_data)
490
- if timer_data.get("timer_id") == self._card_publish_timer_id:
516
+ timer_id = timer_data.get("timer_id")
517
+
518
+ if timer_id == self._card_publish_timer_id:
491
519
  publish_agent_card(self)
520
+ elif timer_id == self.HEALTH_CHECK_TIMER_ID:
521
+ self._check_agent_health()
492
522
 
493
523
  async def handle_cache_expiry_event(self, cache_data: Dict[str, Any]):
494
524
  """
@@ -863,7 +893,8 @@ class SamAgentComponent(SamComponentBase):
863
893
  peer_tools_to_add = []
864
894
  allowed_peer_descriptions = []
865
895
 
866
- for peer_name, agent_card in self.peer_agents.items():
896
+ # Sort peer agents alphabetically to ensure consistent tool ordering for prompt caching
897
+ for peer_name, agent_card in sorted(self.peer_agents.items()):
867
898
  if not isinstance(agent_card, AgentCard) or peer_name == self_name:
868
899
  continue
869
900
 
@@ -2988,6 +3019,7 @@ class SamAgentComponent(SamComponentBase):
2988
3019
  """Clean up resources on component shutdown."""
2989
3020
  log.info("%s Cleaning up A2A ADK Host Component.", self.log_identifier)
2990
3021
  self.cancel_timer(self._card_publish_timer_id)
3022
+ self.cancel_timer(self.HEALTH_CHECK_TIMER_ID)
2991
3023
 
2992
3024
  cleanup_func_details = self.get_config("agent_cleanup_function")
2993
3025
 
@@ -3148,6 +3180,129 @@ class SamAgentComponent(SamComponentBase):
3148
3180
  For now, using the agent name, but could be made more robust (e.g., hostname + agent name).
3149
3181
  """
3150
3182
  return self.agent_name
3183
+
3184
+ def _check_agent_health(self):
3185
+ """
3186
+ Checks the health of peer agents and de-registers unresponsive ones.
3187
+ This is called periodically by the health check timer.
3188
+ Uses TTL-based expiration to determine if an agent is unresponsive.
3189
+ """
3190
+
3191
+ 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
+
3196
+ log.debug(
3197
+ "%s Health check configuration: interval=%d seconds, TTL=%d seconds",
3198
+ self.log_identifier,
3199
+ health_check_interval,
3200
+ ttl_seconds
3201
+ )
3202
+
3203
+ # Validate configuration values
3204
+ if ttl_seconds <= 0 or health_check_interval <= 0 or ttl_seconds < health_check_interval:
3205
+ log.error(
3206
+ "%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
+ self.log_identifier,
3208
+ ttl_seconds,
3209
+ health_check_interval
3210
+ )
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
+
3213
+ # Get all agent names from the registry
3214
+ agent_names = self.agent_registry.get_agent_names()
3215
+ total_agents = len(agent_names)
3216
+ agents_to_deregister = []
3217
+
3218
+ log.debug("%s Checking health of %d peer agents", self.log_identifier, total_agents)
3219
+
3220
+ for agent_name in agent_names:
3221
+ # Skip our own agent
3222
+ if agent_name == self.agent_name:
3223
+ continue
3224
+
3225
+ # 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
+
3228
+ if is_expired:
3229
+ log.warning(
3230
+ "%s Agent '%s' TTL has expired. De-registering. Time since last seen: %d seconds (TTL: %d seconds)",
3231
+ self.log_identifier,
3232
+ agent_name,
3233
+ time_since_last_seen,
3234
+ ttl_seconds
3235
+ )
3236
+ agents_to_deregister.append(agent_name)
3237
+
3238
+ # De-register unresponsive agents
3239
+ for agent_name in agents_to_deregister:
3240
+ self._deregister_agent(agent_name)
3241
+
3242
+ log.debug(
3243
+ "%s Agent health check completed. Total agents: %d, De-registered: %d",
3244
+ self.log_identifier,
3245
+ total_agents,
3246
+ len(agents_to_deregister)
3247
+ )
3248
+
3249
+ def _deregister_agent(self, agent_name: str):
3250
+ """
3251
+ De-registers an agent from the registry and publishes a de-registration event.
3252
+ """
3253
+ # Remove from registry
3254
+ registry_removed = self.agent_registry.remove_agent(agent_name)
3255
+
3256
+ # Always remove from peer_agents regardless of registry result
3257
+ peer_removed = False
3258
+ if agent_name in self.peer_agents:
3259
+ del self.peer_agents[agent_name]
3260
+ peer_removed = True
3261
+ log.info(
3262
+ "%s Removed agent '%s' from peer_agents dictionary",
3263
+ self.log_identifier,
3264
+ agent_name
3265
+ )
3266
+
3267
+ # Publish de-registration event if agent was in either data structure
3268
+ if registry_removed or peer_removed:
3269
+ try:
3270
+ # Create a de-registration event topic
3271
+ namespace = self.get_config("namespace")
3272
+ deregistration_topic = f"{namespace}/a2a/events/agent/deregistered"
3273
+
3274
+ current_time = time.time()
3275
+
3276
+ # Create the payload
3277
+ deregistration_payload = {
3278
+ "event_type": "agent.deregistered",
3279
+ "agent_name": agent_name,
3280
+ "reason": "health_check_failure",
3281
+ "metadata": {
3282
+ "timestamp": current_time,
3283
+ "deregistered_by": self.agent_name
3284
+ }
3285
+ }
3286
+
3287
+ # Publish the event
3288
+ self.publish_a2a_message(
3289
+ payload=deregistration_payload,
3290
+ topic=deregistration_topic
3291
+ )
3292
+
3293
+ log.info(
3294
+ "%s Published de-registration event for agent '%s' to topic '%s'",
3295
+ self.log_identifier,
3296
+ agent_name,
3297
+ deregistration_topic
3298
+ )
3299
+ except Exception as e:
3300
+ log.error(
3301
+ "%s Failed to publish de-registration event for agent '%s': %s",
3302
+ self.log_identifier,
3303
+ agent_name,
3304
+ e
3305
+ )
3151
3306
 
3152
3307
  async def _resolve_early_embeds_and_handle_signals(
3153
3308
  self, raw_text: str, a2a_context: Dict
@@ -2,6 +2,7 @@
2
2
  Collection of Python tools for audio processing and text-to-speech generation.
3
3
  """
4
4
 
5
+ import logging
5
6
  import asyncio
6
7
  import inspect
7
8
  import io
@@ -20,11 +21,11 @@ from google import genai
20
21
  from google.genai import types as adk_types
21
22
  from google.adk.tools import ToolContext
22
23
  from pydub import AudioSegment
23
- from solace_ai_connector.common.log import log
24
24
 
25
25
  from ...agent.utils.artifact_helpers import (
26
26
  load_artifact_content_or_metadata,
27
27
  save_artifact_with_metadata,
28
+ ensure_correct_extension,
28
29
  DEFAULT_SCHEMA_MAX_KEYS,
29
30
  )
30
31
  from ...agent.utils.context_helpers import get_original_session_id
@@ -32,6 +33,7 @@ from ...agent.utils.context_helpers import get_original_session_id
32
33
  from .tool_definition import BuiltinTool
33
34
  from .registry import tool_registry
34
35
 
36
+ log = logging.getLogger(__name__)
35
37
 
36
38
  VOICE_TONE_MAPPING = {
37
39
  "bright": ["Zephyr", "Autonoe"],
@@ -1209,14 +1211,18 @@ async def concatenate_audio(
1209
1211
 
1210
1212
  async def transcribe_audio(
1211
1213
  audio_filename: str,
1214
+ output_filename: Optional[str] = None,
1215
+ description: Optional[str] = None,
1212
1216
  tool_context: ToolContext = None,
1213
1217
  tool_config: Optional[Dict[str, Any]] = None,
1214
1218
  ) -> Dict[str, Any]:
1215
1219
  """
1216
- Transcribes an audio recording using an OpenAI-compatible audio transcription API.
1220
+ Transcribes an audio recording and saves the transcription as a text artifact.
1217
1221
 
1218
1222
  Args:
1219
1223
  audio_filename: The filename (and optional :version) of the input audio artifact.
1224
+ output_filename: Optional filename for the transcription text file (without extension).
1225
+ description: Optional description of the transcription for metadata.
1220
1226
  tool_context: The context provided by the ADK framework.
1221
1227
  tool_config: Configuration dictionary containing model, api_base, api_key.
1222
1228
 
@@ -1224,9 +1230,10 @@ async def transcribe_audio(
1224
1230
  A dictionary containing:
1225
1231
  - "status": "success" or "error".
1226
1232
  - "message": A descriptive message about the outcome.
1227
- - "transcription": The transcribed text from the API (if successful).
1228
- - "audio_filename": The name of the input audio artifact (if successful).
1229
- - "audio_version": The version of the input audio artifact (if successful).
1233
+ - "output_filename": The name of the saved transcription artifact.
1234
+ - "output_version": The version of the saved transcription artifact.
1235
+ - "audio_filename": The name of the input audio artifact.
1236
+ - "audio_version": The version of the input audio artifact.
1230
1237
  """
1231
1238
  log_identifier = f"[AudioTools:transcribe_audio:{audio_filename}]"
1232
1239
  if not tool_context:
@@ -1339,8 +1346,28 @@ async def transcribe_audio(
1339
1346
  )
1340
1347
 
1341
1348
  audio_bytes = audio_artifact_part.inline_data.data
1349
+ audio_mime_type = audio_artifact_part.inline_data.mime_type or "application/octet-stream"
1342
1350
  log.debug(f"{log_identifier} Loaded audio artifact: {len(audio_bytes)} bytes")
1343
1351
 
1352
+ # Load source audio metadata to copy description
1353
+ source_audio_metadata = {}
1354
+ try:
1355
+ metadata_result = await load_artifact_content_or_metadata(
1356
+ artifact_service=artifact_service,
1357
+ app_name=app_name,
1358
+ user_id=user_id,
1359
+ session_id=session_id,
1360
+ filename=filename_base_for_load,
1361
+ version=version_to_load,
1362
+ load_metadata_only=True,
1363
+ log_identifier_prefix=f"{log_identifier}[source_metadata]",
1364
+ )
1365
+ if metadata_result.get("status") == "success":
1366
+ source_audio_metadata = metadata_result.get("metadata", {})
1367
+ log.debug(f"{log_identifier} Loaded source audio metadata")
1368
+ except Exception as meta_err:
1369
+ log.warning(f"{log_identifier} Could not load source audio metadata: {meta_err}")
1370
+
1344
1371
  temp_file_path = None
1345
1372
  try:
1346
1373
  file_ext = os.path.splitext(filename_base_for_load)[1]
@@ -1382,12 +1409,93 @@ async def transcribe_audio(
1382
1409
  f"{log_identifier} Audio transcribed successfully. Transcription length: {len(transcription)} characters"
1383
1410
  )
1384
1411
 
1412
+ # Determine output filename
1413
+ if output_filename:
1414
+ final_filename = ensure_correct_extension(output_filename, "txt")
1415
+ else:
1416
+ # Auto-generate from source audio filename
1417
+ base_name = os.path.splitext(filename_base_for_load)[0]
1418
+ final_filename = f"{base_name}_transcription.txt"
1419
+
1420
+ # Build comprehensive metadata
1421
+ transcription_word_count = len(transcription.split())
1422
+ transcription_char_count = len(transcription)
1423
+
1424
+ # Build description from multiple sources
1425
+ description_parts = []
1426
+
1427
+ # Add user-provided description
1428
+ if description:
1429
+ description_parts.append(description)
1430
+
1431
+ # Add source audio description if available
1432
+ source_description = source_audio_metadata.get("description")
1433
+ if source_description:
1434
+ description_parts.append(f"Source: {source_description}")
1435
+
1436
+ # Add source audio info
1437
+ description_parts.append(f"Transcribed from audio file '{filename_base_for_load}' (version {version_to_load}, {audio_mime_type})")
1438
+
1439
+ # Combine all description parts
1440
+ final_description = ". ".join(description_parts)
1441
+
1442
+ metadata = {
1443
+ "description": final_description,
1444
+ "source_audio_filename": filename_base_for_load,
1445
+ "source_audio_version": version_to_load,
1446
+ "source_audio_mime_type": audio_mime_type,
1447
+ "transcription_model": model_name,
1448
+ "transcription_timestamp": datetime.now(timezone.utc).isoformat(),
1449
+ "transcription_word_count": transcription_word_count,
1450
+ "transcription_char_count": transcription_char_count,
1451
+ "generation_tool": "transcribe_audio",
1452
+ }
1453
+
1454
+ # Copy source audio description separately for reference
1455
+ if source_description:
1456
+ metadata["source_audio_description"] = source_description
1457
+
1458
+ # Add user-provided description separately if provided
1459
+ if description:
1460
+ metadata["user_provided_description"] = description
1461
+
1462
+ # Save transcription as text artifact
1463
+ transcription_bytes = transcription.encode("utf-8")
1464
+
1465
+ save_result = await save_artifact_with_metadata(
1466
+ artifact_service=artifact_service,
1467
+ app_name=app_name,
1468
+ user_id=user_id,
1469
+ session_id=session_id,
1470
+ filename=final_filename,
1471
+ content_bytes=transcription_bytes,
1472
+ mime_type="text/plain",
1473
+ metadata_dict=metadata,
1474
+ timestamp=datetime.now(timezone.utc),
1475
+ schema_max_keys=DEFAULT_SCHEMA_MAX_KEYS,
1476
+ tool_context=tool_context,
1477
+ )
1478
+
1479
+ if save_result.get("status") != "success":
1480
+ error_msg = save_result.get("message", "Failed to save transcription artifact")
1481
+ log.error(f"{log_identifier} {error_msg}")
1482
+ return {
1483
+ "status": "error",
1484
+ "message": f"Transcription succeeded but failed to save as artifact: {error_msg}",
1485
+ }
1486
+
1487
+ log.info(
1488
+ f"{log_identifier} Transcription saved to '{final_filename}' v{save_result['data_version']}"
1489
+ )
1490
+
1385
1491
  return {
1386
1492
  "status": "success",
1387
- "message": "Audio transcribed successfully",
1388
- "transcription": transcription,
1493
+ "message": "Audio transcribed and saved successfully",
1494
+ "output_filename": final_filename,
1495
+ "output_version": save_result["data_version"],
1389
1496
  "audio_filename": filename_base_for_load,
1390
1497
  "audio_version": version_to_load,
1498
+ "result_preview": f"Transcription saved to '{final_filename}' (v{save_result['data_version']}). Length: {transcription_char_count} characters, {transcription_word_count} words."
1391
1499
  }
1392
1500
 
1393
1501
  finally:
@@ -1599,9 +1707,9 @@ concatenate_audio_tool_def = BuiltinTool(
1599
1707
  transcribe_audio_tool_def = BuiltinTool(
1600
1708
  name="transcribe_audio",
1601
1709
  implementation=transcribe_audio,
1602
- description="Transcribes an audio recording using an OpenAI-compatible audio transcription API.",
1710
+ description="Transcribes an audio recording and saves the transcription as a text artifact.",
1603
1711
  category="audio",
1604
- required_scopes=["tool:audio:transcribe"],
1712
+ required_scopes=["tool:audio:transcribe", "tool:artifact:create"],
1605
1713
  parameters=adk_types.Schema(
1606
1714
  type=adk_types.Type.OBJECT,
1607
1715
  properties={
@@ -1609,6 +1717,16 @@ transcribe_audio_tool_def = BuiltinTool(
1609
1717
  type=adk_types.Type.STRING,
1610
1718
  description="The filename (and optional :version) of the input audio artifact.",
1611
1719
  ),
1720
+ "output_filename": adk_types.Schema(
1721
+ type=adk_types.Type.STRING,
1722
+ description="Optional filename for the transcription text file (without .txt extension). If not provided, will auto-generate from source audio filename.",
1723
+ nullable=True,
1724
+ ),
1725
+ "description": adk_types.Schema(
1726
+ type=adk_types.Type.STRING,
1727
+ description="Optional description of the transcription for metadata (e.g., 'Transcription of customer support call about billing inquiry'). Will be combined with source audio description if available.",
1728
+ nullable=True,
1729
+ ),
1612
1730
  },
1613
1731
  required=["audio_filename"],
1614
1732
  ),
@@ -5,6 +5,7 @@ use state_delta for signaling artifact return requests to the host component.
5
5
  Metadata handling is integrated via artifact_helpers.
6
6
  """
7
7
 
8
+ import logging
8
9
  import uuid
9
10
  import json
10
11
  import re
@@ -16,7 +17,6 @@ from google.adk.tools import ToolContext
16
17
  if TYPE_CHECKING:
17
18
  from google.adk.agents.invocation_context import InvocationContext
18
19
  from google.genai import types as adk_types
19
- from solace_ai_connector.common.log import log
20
20
  from .tool_definition import BuiltinTool
21
21
  from .registry import tool_registry
22
22
  from ...agent.utils.artifact_helpers import (
@@ -38,6 +38,8 @@ from google.adk.models import LlmRequest
38
38
  from google.adk.models.registry import LLMRegistry
39
39
  from ...common.utils.mime_helpers import is_text_based_file
40
40
 
41
+ log = logging.getLogger(__name__)
42
+
41
43
  CATEGORY_NAME = "Artifact Management"
42
44
  CATEGORY_DESCRIPTION = "List, read, create, update, and delete artifacts."
43
45
 
@@ -2,6 +2,7 @@
2
2
  Built-in ADK Tools for Data Analysis (SQL, JQ, Plotly).
3
3
  """
4
4
 
5
+ import logging
5
6
  import json
6
7
  from typing import Any, Dict, Tuple, Optional, Literal
7
8
  from datetime import datetime, timezone
@@ -31,7 +32,6 @@ except ImportError:
31
32
 
32
33
  from google.adk.tools import ToolContext
33
34
  from google.genai import types as adk_types
34
- from solace_ai_connector.common.log import log
35
35
 
36
36
  from ...agent.utils.artifact_helpers import (
37
37
  ensure_correct_extension,
@@ -44,6 +44,8 @@ from ...agent.utils.context_helpers import get_original_session_id
44
44
  from .tool_definition import BuiltinTool
45
45
  from .registry import tool_registry
46
46
 
47
+ log = logging.getLogger(__name__)
48
+
47
49
  CATEGORY_NAME = "Data Analysis"
48
50
  CATEGORY_DESCRIPTION = "Create static chart images from data in JSON or YAML format."
49
51