solace-agent-mesh 1.7.1__py3-none-any.whl → 1.13.2__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (447) hide show
  1. solace_agent_mesh/agent/adk/alembic/README +74 -0
  2. solace_agent_mesh/agent/adk/alembic/env.py +77 -0
  3. solace_agent_mesh/agent/adk/alembic/script.py.mako +28 -0
  4. solace_agent_mesh/agent/adk/alembic/versions/e2902798564d_adk_session_db_upgrade.py +52 -0
  5. solace_agent_mesh/agent/adk/alembic.ini +112 -0
  6. solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +164 -0
  7. solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
  8. solace_agent_mesh/agent/adk/callbacks.py +752 -127
  9. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +99 -7
  10. solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +52 -5
  11. solace_agent_mesh/agent/adk/mcp_content_processor.py +1 -1
  12. solace_agent_mesh/agent/adk/models/lite_llm.py +34 -16
  13. solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
  14. solace_agent_mesh/agent/adk/runner.py +66 -8
  15. solace_agent_mesh/agent/adk/schema_migration.py +88 -0
  16. solace_agent_mesh/agent/adk/services.py +41 -1
  17. solace_agent_mesh/agent/adk/setup.py +220 -32
  18. solace_agent_mesh/agent/adk/stream_parser.py +229 -40
  19. solace_agent_mesh/agent/protocol/event_handlers.py +219 -33
  20. solace_agent_mesh/agent/proxies/a2a/component.py +572 -75
  21. solace_agent_mesh/agent/proxies/a2a/config.py +80 -4
  22. solace_agent_mesh/agent/proxies/base/component.py +188 -22
  23. solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
  24. solace_agent_mesh/agent/sac/app.py +37 -12
  25. solace_agent_mesh/agent/sac/component.py +322 -52
  26. solace_agent_mesh/agent/sac/patch_adk.py +8 -16
  27. solace_agent_mesh/agent/sac/task_execution_context.py +90 -0
  28. solace_agent_mesh/agent/tools/__init__.py +3 -0
  29. solace_agent_mesh/agent/tools/audio_tools.py +3 -3
  30. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +698 -24
  31. solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
  32. solace_agent_mesh/agent/tools/peer_agent_tool.py +82 -15
  33. solace_agent_mesh/agent/tools/time_tools.py +126 -0
  34. solace_agent_mesh/agent/tools/tool_config_types.py +54 -2
  35. solace_agent_mesh/agent/tools/web_search_tools.py +279 -0
  36. solace_agent_mesh/agent/tools/web_tools.py +125 -17
  37. solace_agent_mesh/agent/utils/artifact_helpers.py +243 -5
  38. solace_agent_mesh/agent/utils/context_helpers.py +17 -0
  39. solace_agent_mesh/assets/docs/404.html +6 -6
  40. solace_agent_mesh/assets/docs/assets/css/{styles.906a1503.css → styles.8162edfb.css} +1 -1
  41. solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
  42. solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
  43. solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.js +1 -0
  44. solace_agent_mesh/assets/docs/assets/js/17896441.e612dfb4.js +1 -0
  45. solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
  46. solace_agent_mesh/assets/docs/assets/js/{17896441.a5e82f9b.js.LICENSE.txt → 2279.550aa580.js.LICENSE.txt} +6 -0
  47. solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/3ac1795d.7f7ab1c1.js +1 -0
  51. solace_agent_mesh/assets/docs/assets/js/3ff0015d.e53c9b78.js +1 -0
  52. solace_agent_mesh/assets/docs/assets/js/41adc471.0e95b87c.js +1 -0
  53. solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
  54. solace_agent_mesh/assets/docs/assets/js/49eed117.493d6f99.js +1 -0
  55. solace_agent_mesh/assets/docs/assets/js/{509e993c.4c7a1a6d.js → 509e993c.a1fbf45a.js} +1 -1
  56. solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
  57. solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
  59. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
  60. solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
  61. solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
  62. solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
  63. solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
  64. solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
  65. solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
  66. solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
  67. solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
  68. solace_agent_mesh/assets/docs/assets/js/81a99df0.7ed65d45.js +1 -0
  69. solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
  70. solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
  71. solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.js +1 -0
  72. solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
  73. solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
  74. solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
  75. solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
  76. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
  77. solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
  78. solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
  79. solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
  80. solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
  81. solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
  82. solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
  83. solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
  84. solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
  85. solace_agent_mesh/assets/docs/assets/js/f284c35a.cc97854c.js +1 -0
  86. solace_agent_mesh/assets/docs/assets/js/main.d634009f.js +2 -0
  87. solace_agent_mesh/assets/docs/assets/js/runtime~main.27bb82a7.js +1 -0
  88. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +68 -68
  89. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +50 -50
  90. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +42 -42
  91. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +55 -55
  92. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +75 -75
  93. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
  94. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +67 -50
  95. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/research-tools/index.html +136 -0
  96. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +178 -144
  97. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +43 -42
  98. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +20 -18
  99. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +23 -23
  100. solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
  101. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +45 -45
  102. solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +98 -112
  103. solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
  104. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +208 -125
  105. solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
  106. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +28 -28
  107. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -29
  108. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +14 -14
  109. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/index.html +47 -0
  110. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
  111. solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +67 -53
  112. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -17
  113. solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
  114. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +38 -38
  115. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +87 -87
  116. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +67 -49
  117. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +17 -17
  118. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +51 -51
  119. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +22 -22
  120. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +27 -27
  121. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +135 -135
  122. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +66 -66
  123. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +51 -51
  124. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +50 -38
  125. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +86 -86
  126. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +51 -51
  127. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +24 -24
  128. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +30 -30
  129. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +44 -44
  130. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
  131. solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +50 -23
  132. solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +29 -24
  133. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +21 -21
  134. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +40 -37
  135. solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
  136. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +96 -66
  137. solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +181 -181
  138. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +75 -75
  139. solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +27 -27
  140. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +44 -44
  141. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +39 -38
  142. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +30 -30
  143. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +18 -18
  144. solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
  145. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +135 -114
  146. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +37 -37
  147. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +14 -14
  148. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +27 -25
  149. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +69 -69
  150. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +72 -72
  151. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +112 -112
  152. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +28 -28
  153. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +42 -42
  154. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +20 -20
  155. solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
  156. solace_agent_mesh/assets/docs/lunr-index-1768329217460.json +1 -0
  157. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  158. solace_agent_mesh/assets/docs/search-doc-1768329217460.json +1 -0
  159. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  160. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  161. solace_agent_mesh/cli/__init__.py +1 -1
  162. solace_agent_mesh/cli/commands/add_cmd/__init__.py +3 -1
  163. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +6 -1
  164. solace_agent_mesh/cli/commands/add_cmd/proxy_cmd.py +100 -0
  165. solace_agent_mesh/cli/commands/eval_cmd.py +1 -1
  166. solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
  167. solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
  168. solace_agent_mesh/cli/commands/init_cmd/env_step.py +30 -3
  169. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +3 -4
  170. solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
  171. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +16 -3
  172. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +2 -1
  173. solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
  174. solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +3 -3
  175. solace_agent_mesh/cli/commands/run_cmd.py +64 -49
  176. solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
  177. solace_agent_mesh/cli/main.py +15 -0
  178. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-tcIFZLis.js → authCallback-KnKMP_vb.js} +1 -1
  179. solace_agent_mesh/client/webui/frontend/static/assets/client-DpBL2stg.js +25 -0
  180. solace_agent_mesh/client/webui/frontend/static/assets/main-Cd498TV2.js +435 -0
  181. solace_agent_mesh/client/webui/frontend/static/assets/main-rSf8Vu29.css +1 -0
  182. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-CINwxvwV.js → vendor-CGk8Suyh.js} +189 -94
  183. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  184. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  185. solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
  186. solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
  187. solace_agent_mesh/common/a2a/types.py +1 -1
  188. solace_agent_mesh/common/agent_registry.py +38 -11
  189. solace_agent_mesh/common/data_parts.py +124 -0
  190. solace_agent_mesh/common/error_handlers.py +83 -0
  191. solace_agent_mesh/common/exceptions.py +24 -0
  192. solace_agent_mesh/common/oauth/__init__.py +17 -0
  193. solace_agent_mesh/common/oauth/oauth_client.py +408 -0
  194. solace_agent_mesh/common/oauth/utils.py +50 -0
  195. solace_agent_mesh/common/rag_dto.py +156 -0
  196. solace_agent_mesh/common/sac/sam_component_base.py +73 -1
  197. solace_agent_mesh/common/sam_events/event_service.py +2 -2
  198. solace_agent_mesh/common/utils/embeds/converter.py +1 -8
  199. solace_agent_mesh/common/utils/embeds/modifiers.py +2 -27
  200. solace_agent_mesh/common/utils/embeds/resolver.py +94 -25
  201. solace_agent_mesh/common/utils/embeds/types.py +1 -0
  202. solace_agent_mesh/common/utils/log_formatters.py +20 -0
  203. solace_agent_mesh/common/utils/mime_helpers.py +12 -5
  204. solace_agent_mesh/common/utils/rbac_utils.py +69 -0
  205. solace_agent_mesh/common/utils/templates/__init__.py +8 -0
  206. solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
  207. solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
  208. solace_agent_mesh/config_portal/backend/common.py +12 -0
  209. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-CljP4_mv.js +103 -0
  210. solace_agent_mesh/config_portal/frontend/static/client/assets/{components-Rk0n-9cK.js → components-CaC6hG8d.js} +22 -22
  211. solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-mvZjNKiz.js → entry.client-H_TM0YBt.js} +3 -3
  212. solace_agent_mesh/config_portal/frontend/static/client/assets/{index-DzNKzXrc.js → index-CnFykb2v.js} +16 -16
  213. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-f8439d40.js +1 -0
  214. solace_agent_mesh/config_portal/frontend/static/client/assets/root-BIMqslJB.css +1 -0
  215. solace_agent_mesh/config_portal/frontend/static/client/assets/root-mJmTIdIk.js +10 -0
  216. solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
  217. solace_agent_mesh/core_a2a/service.py +3 -2
  218. solace_agent_mesh/gateway/adapter/base.py +28 -1
  219. solace_agent_mesh/gateway/adapter/types.py +9 -0
  220. solace_agent_mesh/gateway/base/app.py +10 -0
  221. solace_agent_mesh/gateway/base/auth_interface.py +103 -0
  222. solace_agent_mesh/gateway/base/component.py +451 -10
  223. solace_agent_mesh/gateway/generic/component.py +274 -30
  224. solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
  225. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +2 -43
  226. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +2 -2
  227. solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
  228. solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
  229. solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
  230. solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
  231. solace_agent_mesh/gateway/http_sse/alembic.ini +0 -36
  232. solace_agent_mesh/gateway/http_sse/app.py +23 -6
  233. solace_agent_mesh/gateway/http_sse/component.py +158 -73
  234. solace_agent_mesh/gateway/http_sse/dependencies.py +50 -57
  235. solace_agent_mesh/gateway/http_sse/main.py +58 -482
  236. solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
  237. solace_agent_mesh/gateway/http_sse/repository/entities/project.py +1 -1
  238. solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +1 -1
  239. solace_agent_mesh/gateway/http_sse/repository/entities/session.py +3 -2
  240. solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
  241. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +2 -2
  242. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +2 -2
  243. solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +5 -0
  244. solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
  245. solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +1 -1
  246. solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
  247. solace_agent_mesh/gateway/http_sse/repository/project_repository.py +1 -1
  248. solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +1 -1
  249. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +12 -107
  250. solace_agent_mesh/gateway/http_sse/repository/task_repository.py +86 -2
  251. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +38 -7
  252. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +113 -7
  253. solace_agent_mesh/gateway/http_sse/routers/auth.py +69 -132
  254. solace_agent_mesh/gateway/http_sse/routers/config.py +235 -10
  255. solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
  256. solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
  257. solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +1 -1
  258. solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
  259. solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +1 -0
  260. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +3 -2
  261. solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
  262. solace_agent_mesh/gateway/http_sse/routers/feedback.py +2 -2
  263. solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
  264. solace_agent_mesh/gateway/http_sse/routers/projects.py +250 -24
  265. solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
  266. solace_agent_mesh/gateway/http_sse/routers/sessions.py +14 -5
  267. solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
  268. solace_agent_mesh/gateway/http_sse/routers/sse.py +117 -4
  269. solace_agent_mesh/gateway/http_sse/routers/tasks.py +509 -149
  270. solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
  271. solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
  272. solace_agent_mesh/gateway/http_sse/routers/visualization.py +2 -1
  273. solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
  274. solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
  275. solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
  276. solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
  277. solace_agent_mesh/gateway/http_sse/services/project_service.py +539 -12
  278. solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
  279. solace_agent_mesh/gateway/http_sse/services/session_service.py +198 -21
  280. solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
  281. solace_agent_mesh/gateway/http_sse/sse_manager.py +280 -169
  282. solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
  283. solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +41 -1
  284. solace_agent_mesh/services/__init__.py +0 -0
  285. solace_agent_mesh/services/platform/__init__.py +29 -0
  286. solace_agent_mesh/services/platform/alembic/env.py +85 -0
  287. solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
  288. solace_agent_mesh/services/platform/alembic.ini +109 -0
  289. solace_agent_mesh/services/platform/api/__init__.py +3 -0
  290. solace_agent_mesh/services/platform/api/dependencies.py +154 -0
  291. solace_agent_mesh/services/platform/api/main.py +314 -0
  292. solace_agent_mesh/services/platform/api/middleware.py +51 -0
  293. solace_agent_mesh/services/platform/api/routers/__init__.py +33 -0
  294. solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
  295. solace_agent_mesh/services/platform/app.py +215 -0
  296. solace_agent_mesh/services/platform/component.py +777 -0
  297. solace_agent_mesh/shared/__init__.py +14 -0
  298. solace_agent_mesh/shared/api/__init__.py +42 -0
  299. solace_agent_mesh/shared/auth/__init__.py +26 -0
  300. solace_agent_mesh/shared/auth/dependencies.py +204 -0
  301. solace_agent_mesh/shared/auth/middleware.py +347 -0
  302. solace_agent_mesh/shared/database/__init__.py +20 -0
  303. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
  304. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
  305. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
  306. solace_agent_mesh/shared/exceptions/__init__.py +36 -0
  307. solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +1 -1
  308. solace_agent_mesh/shared/utils/__init__.py +21 -0
  309. solace_agent_mesh/templates/logging_config_template.yaml +48 -0
  310. solace_agent_mesh/templates/main_orchestrator.yaml +12 -1
  311. solace_agent_mesh/templates/platform.yaml +49 -0
  312. solace_agent_mesh/templates/plugin_readme_template.md +3 -25
  313. solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
  314. solace_agent_mesh/templates/proxy_template.yaml +62 -0
  315. solace_agent_mesh/templates/webui.yaml +148 -6
  316. solace_agent_mesh/tools/web_search/__init__.py +18 -0
  317. solace_agent_mesh/tools/web_search/base.py +84 -0
  318. solace_agent_mesh/tools/web_search/google_search.py +247 -0
  319. solace_agent_mesh/tools/web_search/models.py +99 -0
  320. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +29 -8
  321. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/RECORD +334 -313
  322. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
  323. solace_agent_mesh/agent/adk/adk_llm.txt +0 -226
  324. solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
  325. solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
  326. solace_agent_mesh/agent/adk/models/models_llm.txt +0 -189
  327. solace_agent_mesh/agent/agent_llm.txt +0 -369
  328. solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
  329. solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
  330. solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
  331. solace_agent_mesh/agent/proxies/a2a/a2a_llm.txt +0 -190
  332. solace_agent_mesh/agent/proxies/base/base_llm.txt +0 -148
  333. solace_agent_mesh/agent/proxies/proxies_llm.txt +0 -283
  334. solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
  335. solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
  336. solace_agent_mesh/agent/testing/testing_llm.txt +0 -58
  337. solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
  338. solace_agent_mesh/agent/tools/tools_llm.txt +0 -276
  339. solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -275
  340. solace_agent_mesh/agent/utils/utils_llm.txt +0 -152
  341. solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
  342. solace_agent_mesh/assets/docs/assets/js/05749d90.c70b2be9.js +0 -1
  343. solace_agent_mesh/assets/docs/assets/js/15ba94aa.92fea363.js +0 -1
  344. solace_agent_mesh/assets/docs/assets/js/15e40e79.36003774.js +0 -1
  345. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
  346. solace_agent_mesh/assets/docs/assets/js/240a0364.c39f8388.js +0 -1
  347. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
  348. solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
  349. solace_agent_mesh/assets/docs/assets/js/3ac1795d.e4870a49.js +0 -1
  350. solace_agent_mesh/assets/docs/assets/js/3ff0015d.b63ee53a.js +0 -1
  351. solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +0 -1
  352. solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
  353. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.45b32c2b.js +0 -1
  354. solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +0 -1
  355. solace_agent_mesh/assets/docs/assets/js/66d4869e.830d443f.js +0 -1
  356. solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
  357. solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.js +0 -1
  358. solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +0 -1
  359. solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +0 -1
  360. solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +0 -1
  361. solace_agent_mesh/assets/docs/assets/js/94e8668d.09ed9234.js +0 -1
  362. solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +0 -1
  363. solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +0 -1
  364. solace_agent_mesh/assets/docs/assets/js/ab9708a8.245ae0ef.js +0 -1
  365. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
  366. solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.f902fad8.js +0 -1
  367. solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +0 -1
  368. solace_agent_mesh/assets/docs/assets/js/e04b235d.c9c50c7b.js +0 -1
  369. solace_agent_mesh/assets/docs/assets/js/e3d9abda.d11c67a7.js +0 -1
  370. solace_agent_mesh/assets/docs/assets/js/e6f9706b.045d0fa1.js +0 -1
  371. solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +0 -1
  372. solace_agent_mesh/assets/docs/assets/js/f284c35a.5099c51e.js +0 -1
  373. solace_agent_mesh/assets/docs/assets/js/main.f213fe0c.js +0 -2
  374. solace_agent_mesh/assets/docs/assets/js/runtime~main.d9606d6a.js +0 -1
  375. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes-deployment/index.html +0 -47
  376. solace_agent_mesh/assets/docs/lunr-index-1762283454666.json +0 -1
  377. solace_agent_mesh/assets/docs/search-doc-1762283454666.json +0 -1
  378. solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
  379. solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
  380. solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
  381. solace_agent_mesh/client/webui/frontend/static/assets/client-CRYdKo2Q.js +0 -25
  382. solace_agent_mesh/client/webui/frontend/static/assets/main-CojeY_1w.css +0 -1
  383. solace_agent_mesh/client/webui/frontend/static/assets/main-ILja9MCG.js +0 -353
  384. solace_agent_mesh/common/a2a/a2a_llm.txt +0 -175
  385. solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
  386. solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -445
  387. solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
  388. solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -330
  389. solace_agent_mesh/common/common_llm.txt +0 -230
  390. solace_agent_mesh/common/common_llm_detail.txt +0 -2562
  391. solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
  392. solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
  393. solace_agent_mesh/common/sac/sac_llm.txt +0 -71
  394. solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
  395. solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
  396. solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
  397. solace_agent_mesh/common/services/providers/providers_llm.txt +0 -81
  398. solace_agent_mesh/common/services/services_llm.txt +0 -368
  399. solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
  400. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
  401. solace_agent_mesh/common/utils/utils_llm.txt +0 -335
  402. solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
  403. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +0 -98
  404. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-61038fc6.js +0 -1
  405. solace_agent_mesh/config_portal/frontend/static/client/assets/root-BWvk5-gF.js +0 -10
  406. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +0 -1
  407. solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
  408. solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
  409. solace_agent_mesh/gateway/base/base_llm.txt +0 -226
  410. solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
  411. solace_agent_mesh/gateway/gateway_llm.txt +0 -369
  412. solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
  413. solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -345
  414. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_fulltext_search_indexes.py +0 -92
  415. solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -161
  416. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
  417. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
  418. solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
  419. solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -221
  420. solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -257
  421. solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -308
  422. solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -450
  423. solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -133
  424. solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -123
  425. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -312
  426. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -303
  427. solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
  428. solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -319
  429. solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
  430. solace_agent_mesh/llm.txt +0 -228
  431. solace_agent_mesh/llm_detail.txt +0 -2835
  432. solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
  433. solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
  434. solace_agent_mesh/templates/logging_config_template.ini +0 -45
  435. solace_agent_mesh/templates/templates_llm.txt +0 -147
  436. /solace_agent_mesh/assets/docs/assets/js/{main.f213fe0c.js.LICENSE.txt → main.d634009f.js.LICENSE.txt} +0 -0
  437. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
  438. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
  439. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
  440. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
  441. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
  442. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
  443. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
  444. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
  445. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
  446. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
  447. {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
@@ -11,11 +11,24 @@ from ..base.config import BaseProxyAppConfig, ProxiedAgentConfig
11
11
  from ....common.utils.pydantic_utils import SamConfigBase
12
12
 
13
13
 
14
+ class HttpHeaderConfig(SamConfigBase):
15
+ """Configuration for a single HTTP header."""
16
+
17
+ name: str = Field(
18
+ ...,
19
+ description="The HTTP header name (e.g., 'X-API-Key', 'Authorization').",
20
+ )
21
+ value: str = Field(
22
+ ...,
23
+ description="The HTTP header value.",
24
+ )
25
+
26
+
14
27
  class AuthenticationConfig(SamConfigBase):
15
28
  """Authentication configuration for downstream A2A agents."""
16
29
 
17
30
  type: Optional[
18
- Literal["static_bearer", "static_apikey", "oauth2_client_credentials"]
31
+ Literal["static_bearer", "static_apikey", "oauth2_client_credentials", "oauth2_authorization_code"]
19
32
  ] = Field(
20
33
  default=None,
21
34
  description="Authentication type. If not specified, inferred from 'scheme' for backward compatibility.",
@@ -34,11 +47,11 @@ class AuthenticationConfig(SamConfigBase):
34
47
  )
35
48
  client_id: Optional[str] = Field(
36
49
  default=None,
37
- description="OAuth 2.0 client identifier (required for oauth2_client_credentials type).",
50
+ description="OAuth 2.0 client identifier (required for oauth2_client_credentials and oauth2_authorization_code types).",
38
51
  )
39
52
  client_secret: Optional[str] = Field(
40
53
  default=None,
41
- description="OAuth 2.0 client secret (required for oauth2_client_credentials type).",
54
+ description="OAuth 2.0 client secret (required for oauth2_client_credentials type, optional for oauth2_authorization_code).",
42
55
  )
43
56
  scope: Optional[str] = Field(
44
57
  default=None,
@@ -50,6 +63,20 @@ class AuthenticationConfig(SamConfigBase):
50
63
  description="How long to cache OAuth 2.0 tokens before refresh, in seconds (default: 3300 = 55 minutes).",
51
64
  )
52
65
 
66
+ # NEW fields for oauth2_authorization_code
67
+ authorization_url: Optional[str] = Field(
68
+ default=None,
69
+ description="OAuth 2.0 authorization endpoint URL (for oauth2_authorization_code type). Can override agent card URL.",
70
+ )
71
+ redirect_uri: Optional[str] = Field(
72
+ default=None,
73
+ description="OAuth 2.0 redirect URI (required for oauth2_authorization_code type).",
74
+ )
75
+ scopes: Optional[List[str]] = Field(
76
+ default=None,
77
+ description="OAuth 2.0 scopes as a list of strings (optional for oauth2_authorization_code type).",
78
+ )
79
+
53
80
  @model_validator(mode="after")
54
81
  def validate_auth_config(self) -> "AuthenticationConfig":
55
82
  """Validates authentication configuration based on type."""
@@ -108,10 +135,35 @@ class AuthenticationConfig(SamConfigBase):
108
135
  "OAuth 2.0 client credentials flow requires 'client_secret'."
109
136
  )
110
137
 
138
+ elif auth_type == "oauth2_authorization_code":
139
+ # Validate client_id
140
+ if not self.client_id:
141
+ raise ValueError(
142
+ "OAuth 2.0 authorization code flow requires 'client_id'."
143
+ )
144
+
145
+ # Validate redirect_uri
146
+ if not self.redirect_uri:
147
+ raise ValueError(
148
+ "OAuth 2.0 authorization code flow requires 'redirect_uri'."
149
+ )
150
+
151
+ # Optional: Validate authorization_url if provided (can also come from agent card)
152
+ if self.authorization_url:
153
+ try:
154
+ parsed_url = urlparse(self.authorization_url)
155
+ if parsed_url.scheme not in ["https", "http"]:
156
+ raise ValueError(
157
+ f"OAuth 2.0 'authorization_url' must use HTTP(S). "
158
+ f"Got scheme: '{parsed_url.scheme}'"
159
+ )
160
+ except Exception as e:
161
+ raise ValueError(f"Failed to parse 'authorization_url': {e}")
162
+
111
163
  else:
112
164
  raise ValueError(
113
165
  f"Unsupported authentication type '{auth_type}'. "
114
- f"Supported types: static_bearer, static_apikey, oauth2_client_credentials."
166
+ f"Supported types: static_bearer, static_apikey, oauth2_client_credentials, oauth2_authorization_code."
115
167
  )
116
168
 
117
169
  return self
@@ -128,6 +180,30 @@ class A2AProxiedAgentConfig(ProxiedAgentConfig):
128
180
  default=None,
129
181
  description="Authentication details for the downstream agent.",
130
182
  )
183
+ use_auth_for_agent_card: bool = Field(
184
+ default=False,
185
+ description="If true, applies the configured authentication to agent card fetching. "
186
+ "If false, agent card requests are made without authentication.",
187
+ )
188
+ use_agent_card_url: bool = Field(
189
+ default=True,
190
+ description="If true, uses the URL from the agent card for task invocations. "
191
+ "If false, uses the configured URL directly for task invocations. "
192
+ "Note: The configured URL is always used to fetch the agent card itself.",
193
+ )
194
+ agent_card_headers: Optional[List[HttpHeaderConfig]] = Field(
195
+ default=None,
196
+ description="Custom HTTP headers to include when fetching the agent card. "
197
+ "These headers are added alongside authentication headers.",
198
+ )
199
+ task_headers: Optional[List[HttpHeaderConfig]] = Field(
200
+ default=None,
201
+ description="Custom HTTP headers to include when invoking A2A tasks. "
202
+ "These headers are added alongside authentication headers. Note: The A2A SDK's "
203
+ "AuthInterceptor applies authentication headers after these are set, so custom "
204
+ "headers cannot override authentication. For custom auth, omit the 'authentication' "
205
+ "config and use task_headers to set auth headers directly.",
206
+ )
131
207
 
132
208
 
133
209
  class A2AProxyAppConfig(BaseProxyAppConfig):
@@ -7,8 +7,9 @@ from __future__ import annotations
7
7
  import asyncio
8
8
  import concurrent.futures
9
9
  import threading
10
+ import time
10
11
  from abc import ABC, abstractmethod
11
- from typing import Any, Dict, Optional, TYPE_CHECKING
12
+ from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING
12
13
 
13
14
  import httpx
14
15
 
@@ -32,6 +33,8 @@ from ....common.a2a.protocol import (
32
33
  from a2a.types import (
33
34
  A2ARequest,
34
35
  AgentCard,
36
+ AgentCapabilities,
37
+ AgentExtension,
35
38
  CancelTaskRequest,
36
39
  FilePart,
37
40
  InternalError,
@@ -77,16 +80,22 @@ class BaseProxyComponent(ComponentBase, ABC):
77
80
  "artifact_service", {"type": "memory"}
78
81
  )
79
82
  self.discovery_interval_sec = self.get_config("discovery_interval_seconds", 60)
83
+ self.task_state_ttl_minutes = self.get_config("task_state_ttl_minutes", 60)
84
+ self.task_cleanup_interval_minutes = self.get_config(
85
+ "task_cleanup_interval_minutes", 10
86
+ )
80
87
 
81
88
  self.agent_registry = AgentRegistry()
82
89
  self.artifact_service: Optional[BaseArtifactService] = None
83
- self.active_tasks: Dict[str, ProxyTaskContext] = {}
90
+ # Store (timestamp, ProxyTaskContext) tuples for TTL-based cleanup
91
+ self.active_tasks: Dict[str, Tuple[float, ProxyTaskContext]] = {}
84
92
  self.active_tasks_lock = threading.Lock()
85
93
 
86
94
  self._async_loop: Optional[asyncio.AbstractEventLoop] = None
87
95
  self._async_thread: Optional[threading.Thread] = None
88
96
  self._async_init_future: Optional[concurrent.futures.Future] = None
89
97
  self._discovery_timer_id = f"proxy_discovery_{self.name}"
98
+ self._task_cleanup_timer_id = f"proxy_task_cleanup_{self.name}"
90
99
 
91
100
  try:
92
101
  # Initialize synchronous services first
@@ -158,8 +167,11 @@ class BaseProxyComponent(ComponentBase, ABC):
158
167
  if not hasattr(event, "_proxy_message_handled"):
159
168
  event._proxy_message_handled = message_handled
160
169
  elif event.event_type == EventType.TIMER:
161
- if event.data.get("timer_id") == self._discovery_timer_id:
170
+ timer_id = event.data.get("timer_id")
171
+ if timer_id == self._discovery_timer_id:
162
172
  await self._discover_and_publish_agents()
173
+ elif timer_id == self._task_cleanup_timer_id:
174
+ await self._cleanup_stale_tasks()
163
175
  else:
164
176
  log.debug(
165
177
  "%s Ignoring unhandled event type: %s",
@@ -209,12 +221,13 @@ class BaseProxyComponent(ComponentBase, ABC):
209
221
  "status_topic": message.get_user_properties().get("a2aStatusTopic"),
210
222
  "reply_to_topic": message.get_user_properties().get("replyTo"),
211
223
  "is_streaming": isinstance(a2a_request.root, SendStreamingMessageRequest),
224
+ "user_properties": message.get_user_properties(),
212
225
  }
213
226
  task_context = ProxyTaskContext(
214
227
  task_id=logical_task_id, a2a_context=a2a_context
215
228
  )
216
229
  with self.active_tasks_lock:
217
- self.active_tasks[logical_task_id] = task_context
230
+ self.active_tasks[logical_task_id] = (time.time(), task_context)
218
231
 
219
232
  log.info(
220
233
  "%s Forwarding request for task %s to agent %s.",
@@ -228,12 +241,13 @@ class BaseProxyComponent(ComponentBase, ABC):
228
241
 
229
242
  elif isinstance(a2a_request.root, CancelTaskRequest):
230
243
  logical_task_id = get_task_id_from_cancel_request(a2a_request)
231
-
244
+
232
245
  # Get the agent name from the topic (same as for send_message)
233
246
  target_agent_name = topic.split("/")[-1]
234
-
247
+
235
248
  with self.active_tasks_lock:
236
- task_context = self.active_tasks.get(logical_task_id)
249
+ task_entry = self.active_tasks.get(logical_task_id)
250
+ task_context = task_entry[1] if task_entry else None
237
251
 
238
252
  if task_context:
239
253
  log.info(
@@ -319,6 +333,73 @@ class BaseProxyComponent(ComponentBase, ABC):
319
333
 
320
334
  return update_message_parts(original_message, resolved_parts)
321
335
 
336
+ def _update_agent_card_for_proxy(self, agent_card: AgentCard, agent_alias: str) -> AgentCard:
337
+ """
338
+ Updates an agent card for proxying by:
339
+ 1. Setting the name to the proxy alias
340
+ 2. Adding/updating the display-name extension to preserve the original name
341
+
342
+ Args:
343
+ agent_card: The original agent card fetched from the remote agent
344
+ agent_alias: The alias/name to use for this agent in SAM
345
+
346
+ Returns:
347
+ A modified copy of the agent card with updated name and display-name extension
348
+ """
349
+ # Create a deep copy to avoid modifying the original
350
+ card_copy = agent_card.model_copy(deep=True)
351
+
352
+ # Store the original name as the display name (if not already set)
353
+ # This preserves the agent's identity while allowing it to be proxied under an alias
354
+ original_display_name = agent_card.name
355
+
356
+ # Check if there's already a display-name extension to preserve
357
+ display_name_uri = "https://solace.com/a2a/extensions/display-name"
358
+ if card_copy.capabilities and card_copy.capabilities.extensions:
359
+ for ext in card_copy.capabilities.extensions:
360
+ if ext.uri == display_name_uri and ext.params and ext.params.get("display_name"):
361
+ # Use the existing display name from the extension
362
+ original_display_name = ext.params["display_name"]
363
+ break
364
+
365
+ # Update the card's name to the proxy alias
366
+ card_copy.name = agent_alias
367
+
368
+ # Ensure capabilities and extensions exist
369
+ if not card_copy.capabilities:
370
+ card_copy.capabilities = AgentCapabilities(extensions=[])
371
+ if not card_copy.capabilities.extensions:
372
+ card_copy.capabilities.extensions = []
373
+
374
+ # Find or create the display-name extension
375
+ display_name_ext = None
376
+ for ext in card_copy.capabilities.extensions:
377
+ if ext.uri == display_name_uri:
378
+ display_name_ext = ext
379
+ break
380
+
381
+ if display_name_ext:
382
+ # Update existing extension
383
+ if not display_name_ext.params:
384
+ display_name_ext.params = {}
385
+ display_name_ext.params["display_name"] = original_display_name
386
+ else:
387
+ # Create new extension
388
+ new_ext = AgentExtension(
389
+ uri=display_name_uri,
390
+ params={"display_name": original_display_name}
391
+ )
392
+ card_copy.capabilities.extensions.append(new_ext)
393
+
394
+ log.debug(
395
+ "%s Updated agent card: name='%s', display_name='%s'",
396
+ self.log_identifier,
397
+ agent_alias,
398
+ original_display_name
399
+ )
400
+
401
+ return card_copy
402
+
322
403
  def _initial_discovery_sync(self):
323
404
  """
324
405
  Synchronously fetches agent cards to populate the registry at startup.
@@ -340,12 +421,12 @@ class BaseProxyComponent(ComponentBase, ABC):
340
421
  continue
341
422
  try:
342
423
  # Use a synchronous client for this initial blocking call
343
- response = client.get(f"{agent_url}/.well-known/agent.json")
424
+ response = client.get(f"{agent_url}/.well-known/agent-card.json")
344
425
  response.raise_for_status()
345
426
  agent_card = AgentCard.model_validate(response.json())
346
427
 
347
- card_for_proxy = agent_card.model_copy(deep=True)
348
- card_for_proxy.name = agent_alias
428
+ # Update the card for proxying (preserves display name)
429
+ card_for_proxy = self._update_agent_card_for_proxy(agent_card, agent_alias)
349
430
  self.agent_registry.add_or_update_agent(card_for_proxy)
350
431
  log.info(
351
432
  "%s Initial discovery successful for alias '%s' (actual name: '%s').",
@@ -376,12 +457,12 @@ class BaseProxyComponent(ComponentBase, ABC):
376
457
  continue
377
458
 
378
459
  agent_alias = agent_config["name"]
379
- card_for_proxy = modern_card.model_copy(deep=True)
380
- card_for_proxy.name = agent_alias
381
- self.agent_registry.add_or_update_agent(card_for_proxy)
460
+ # Update the card for proxying (preserves display name)
461
+ card_for_registry = self._update_agent_card_for_proxy(modern_card, agent_alias)
462
+ self.agent_registry.add_or_update_agent(card_for_registry)
382
463
 
383
- # Publish the modern card directly after updating its URL
384
- card_to_publish = card_for_proxy.model_copy(deep=True)
464
+ # Create a separate copy for publishing
465
+ card_to_publish = card_for_registry.model_copy(deep=True)
385
466
  card_to_publish.url = (
386
467
  f"solace:{a2a.get_agent_request_topic(self.namespace, agent_alias)}"
387
468
  )
@@ -418,10 +499,14 @@ class BaseProxyComponent(ComponentBase, ABC):
418
499
  response = create_success_response(
419
500
  result=event, request_id=a2a_context.get("jsonrpc_request_id")
420
501
  )
421
- self._publish_a2a_message(response.model_dump(exclude_none=True), target_topic)
502
+ self._publish_a2a_message(
503
+ response.model_dump(exclude_none=True),
504
+ target_topic,
505
+ user_properties=a2a_context.get("user_properties")
506
+ )
422
507
 
423
- async def _publish_final_response(self, task: Task, a2a_context: Dict):
424
- """Publishes the final Task object to the appropriate Solace topic."""
508
+ async def _publish_task_response(self, task: Task, a2a_context: Dict):
509
+ """Publishes a Task object to the reply topic."""
425
510
  target_topic = a2a_context.get("reply_to_topic")
426
511
  if not target_topic:
427
512
  log.warning(
@@ -434,7 +519,11 @@ class BaseProxyComponent(ComponentBase, ABC):
434
519
  response = create_success_response(
435
520
  result=task, request_id=a2a_context.get("jsonrpc_request_id")
436
521
  )
437
- self._publish_a2a_message(response.model_dump(exclude_none=True), target_topic)
522
+ self._publish_a2a_message(
523
+ response.model_dump(exclude_none=True),
524
+ target_topic,
525
+ user_properties=a2a_context.get("user_properties")
526
+ )
438
527
 
439
528
  async def _publish_artifact_update(
440
529
  self, event: TaskArtifactUpdateEvent, a2a_context: Dict
@@ -452,7 +541,11 @@ class BaseProxyComponent(ComponentBase, ABC):
452
541
  response = create_success_response(
453
542
  result=event, request_id=a2a_context.get("jsonrpc_request_id")
454
543
  )
455
- self._publish_a2a_message(response.model_dump(exclude_none=True), target_topic)
544
+ self._publish_a2a_message(
545
+ response.model_dump(exclude_none=True),
546
+ target_topic,
547
+ user_properties=a2a_context.get("user_properties")
548
+ )
456
549
 
457
550
  async def _publish_error_response(
458
551
  self,
@@ -551,16 +644,73 @@ class BaseProxyComponent(ComponentBase, ABC):
551
644
  nack_e,
552
645
  )
553
646
 
647
+ async def _cleanup_stale_tasks(self):
648
+ """
649
+ Removes task state older than configured TTL.
650
+ This prevents memory leaks from tasks that complete without sending terminal events
651
+ (e.g., due to agent crashes or network failures).
652
+ """
653
+ ttl_seconds = self.task_state_ttl_minutes * 60
654
+ cutoff_time = time.time() - ttl_seconds
655
+
656
+ with self.active_tasks_lock:
657
+ stale_task_ids = [
658
+ task_id
659
+ for task_id, (timestamp, _) in self.active_tasks.items()
660
+ if timestamp < cutoff_time
661
+ ]
662
+ for task_id in stale_task_ids:
663
+ del self.active_tasks[task_id]
664
+ log.warning(
665
+ "%s Cleaned up stale task %s (exceeded TTL of %d minutes)",
666
+ self.log_identifier,
667
+ task_id,
668
+ self.task_state_ttl_minutes,
669
+ )
670
+
671
+ if stale_task_ids:
672
+ log.info(
673
+ "%s Stale task cleanup removed %d tasks",
674
+ self.log_identifier,
675
+ len(stale_task_ids),
676
+ )
677
+
678
+ def _cleanup_task_state(self, task_id: str) -> None:
679
+ """
680
+ Cleans up state for a completed task.
681
+ Called when a terminal event is detected (Task with terminal state,
682
+ or TaskStatusUpdateEvent with final=true).
683
+
684
+ Args:
685
+ task_id: The ID of the task to clean up
686
+ """
687
+ with self.active_tasks_lock:
688
+ entry = self.active_tasks.pop(task_id, None)
689
+ if entry:
690
+ log.info(
691
+ "%s Removed task %s from active_tasks (terminal event detected)",
692
+ self.log_identifier,
693
+ task_id,
694
+ )
695
+ else:
696
+ log.debug(
697
+ "%s Task %s not found in active_tasks during cleanup (already removed)",
698
+ self.log_identifier,
699
+ task_id,
700
+ )
701
+
554
702
  def _publish_discovered_cards(self):
555
703
  """Publishes all agent cards currently in the registry."""
556
704
  log.info(
557
705
  "%s Publishing initially discovered agent cards...", self.log_identifier
558
706
  )
559
707
  for agent_alias in self.agent_registry.get_agent_names():
560
- card_to_publish = self.agent_registry.get_agent(agent_alias)
561
- if not card_to_publish:
708
+ original_card = self.agent_registry.get_agent(agent_alias)
709
+ if not original_card:
562
710
  continue
563
711
 
712
+ # Create a copy for publishing to avoid modifying the card in the registry
713
+ card_to_publish = original_card.model_copy(deep=True)
564
714
  card_to_publish.url = (
565
715
  f"solace:{a2a.get_agent_request_topic(self.namespace, agent_alias)}"
566
716
  )
@@ -599,6 +749,21 @@ class BaseProxyComponent(ComponentBase, ABC):
599
749
  self.discovery_interval_sec,
600
750
  )
601
751
 
752
+ # Schedule the recurring task cleanup timer
753
+ if self.task_cleanup_interval_minutes > 0:
754
+ cleanup_interval_ms = self.task_cleanup_interval_minutes * 60 * 1000
755
+ self.add_timer(
756
+ delay_ms=cleanup_interval_ms,
757
+ timer_id=self._task_cleanup_timer_id,
758
+ interval_ms=cleanup_interval_ms,
759
+ )
760
+ log.info(
761
+ "%s Scheduled recurring stale task cleanup every %d minutes (TTL: %d minutes).",
762
+ self.log_identifier,
763
+ self.task_cleanup_interval_minutes,
764
+ self.task_state_ttl_minutes,
765
+ )
766
+
602
767
  super().run()
603
768
 
604
769
  def clear_client_cache(self):
@@ -614,6 +779,7 @@ class BaseProxyComponent(ComponentBase, ABC):
614
779
  """Cleans up resources on component shutdown."""
615
780
  log.info("%s Cleaning up proxy component.", self.log_identifier)
616
781
  self.cancel_timer(self._discovery_timer_id)
782
+ self.cancel_timer(self._task_cleanup_timer_id)
617
783
 
618
784
  # Clear active tasks (no need to signal cancellation - downstream agents own their tasks)
619
785
  with self.active_tasks_lock:
@@ -13,5 +13,7 @@ class ProxyTaskContext:
13
13
  This object is created when a task is initiated and destroyed when it completes.
14
14
  """
15
15
 
16
- task_id: str
16
+ task_id: str # SAM's task ID (used for upstream communication)
17
17
  a2a_context: Dict[str, Any]
18
+ downstream_task_id: str | None = None # Downstream agent's task ID (used for cancellation)
19
+ original_request: Any = None # Original A2A request (for task pause/resume in OAuth2 flows)
@@ -230,33 +230,33 @@ class ArtifactServiceConfig(SamConfigBase):
230
230
  )
231
231
  return self
232
232
 
233
+
233
234
  class AgentIdentityConfig(SamConfigBase):
234
235
  """Configuration for agent identity and key management."""
236
+
235
237
  key_mode: Literal["auto", "manual"] = Field(
236
238
  default="auto",
237
- description="Key mode for agent identity: 'auto' for automatic generation, 'manual' for user-provided."
239
+ description="Key mode for agent identity: 'auto' for automatic generation, 'manual' for user-provided.",
238
240
  )
239
241
  key_identity: Optional[str] = Field(
240
- default=None,
241
- description="Actual key value when key_mode is 'manual'."
242
+ default=None, description="Actual key value when key_mode is 'manual'."
242
243
  )
243
244
  key_persistence: Optional[str] = Field(
244
245
  default=None,
245
- description="Path to the key file, e.g. '/path/to/keys/agent_{name}.key'."
246
+ description="Path to the key file, e.g. '/path/to/keys/agent_{name}.key'.",
246
247
  )
247
248
 
248
249
  @model_validator(mode="after")
249
250
  def check_key_mode_and_identity(self) -> "AgentIdentityConfig":
250
251
  if self.key_mode == "manual" and not self.key_identity:
251
- raise ValueError(
252
- "'key_identity' is required when 'key_mode' is 'manual'."
253
- )
252
+ raise ValueError("'key_identity' is required when 'key_mode' is 'manual'.")
254
253
  if self.key_mode == "auto" and self.key_identity:
255
254
  log.warning(
256
255
  "Configuration Warning: 'key_identity' is ignored when 'key_mode' is 'auto'."
257
256
  )
258
257
  return self
259
258
 
259
+
260
260
  class SessionServiceConfig(SamConfigBase):
261
261
  """Configuration for the ADK Session Service."""
262
262
 
@@ -298,7 +298,7 @@ class SamAgentAppConfig(SamConfigBase):
298
298
  )
299
299
  agent_identity: Optional[AgentIdentityConfig] = Field(
300
300
  default_factory=lambda: AgentIdentityConfig(key_mode="auto"),
301
- description="Configuration for agent identity and key management."
301
+ description="Configuration for agent identity and key management.",
302
302
  )
303
303
  trust_manager: Optional[Union[TrustManagerConfig, Dict[str, Any]]] = Field(
304
304
  default=None,
@@ -375,6 +375,12 @@ class SamAgentAppConfig(SamConfigBase):
375
375
  ge=0,
376
376
  description="Maximum number of dictionary keys to inspect during schema inference.",
377
377
  )
378
+ schema_inference_depth: int = Field(
379
+ default=4,
380
+ ge=1,
381
+ le=10,
382
+ description="Maximum depth for schema inference on nested structures. Higher values reveal more nested field names but increase metadata size.",
383
+ )
378
384
  enable_embed_resolution: bool = Field(
379
385
  default=True,
380
386
  description="Enable early-stage processing of dynamic embeds and inject related instructions.",
@@ -384,7 +390,7 @@ class SamAgentAppConfig(SamConfigBase):
384
390
  description="If true, automatically attempts to continue LLM generation if it is interrupted by a token limit.",
385
391
  )
386
392
  stream_batching_threshold_bytes: int = Field(
387
- default=0,
393
+ default=100,
388
394
  description="Minimum size in bytes for accumulated text from LLM stream before sending a status update.",
389
395
  )
390
396
  max_message_size_bytes: int = Field(
@@ -476,7 +482,9 @@ class SamAgentApp(App):
476
482
  # Overwrite the raw dict with the validated object for downstream use
477
483
  app_info["app_config"] = app_config
478
484
  except ValidationError as e:
479
- message = SamAgentAppConfig.format_validation_error_message(e, app_info['name'], app_config_dict.get('agent_name'))
485
+ message = SamAgentAppConfig.format_validation_error_message(
486
+ e, app_info["name"], app_config_dict.get("agent_name")
487
+ )
480
488
  log.error("Invalid Agent configuration:\n%s", message)
481
489
  raise
482
490
 
@@ -552,13 +560,30 @@ class SamAgentApp(App):
552
560
  super().__init__(app_info, **kwargs)
553
561
  log.debug("%s Agent initialization complete.", agent_name)
554
562
 
563
+ def run(self):
564
+ """
565
+ Override run to ensure component initialization failures cause application failure.
566
+
567
+ This is critical for containerized deployments where the process must exit with
568
+ a non-zero code if initialization fails. By re-raising the exception, we allow
569
+ the SAC framework's main() to handle cleanup (component.cleanup(), broker
570
+ disconnection, etc.) before exiting with code 1.
571
+ """
572
+ try:
573
+ super().run()
574
+ except Exception as e:
575
+ log.critical(
576
+ "Failed to start agent application '%s': %s", self.name, e, exc_info=e
577
+ )
578
+ raise
579
+
555
580
  def get_component(self, component_name: str = None) -> "SamAgentComponent":
556
581
  """
557
582
  Retrieves the running SamAgentComponent instance from the app's flow.
558
-
583
+
559
584
  Args:
560
585
  component_name: Optional component name (for compatibility, but ignored since there's only one component)
561
-
586
+
562
587
  Returns:
563
588
  The SamAgentComponent instance or None if not found
564
589
  """