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
@@ -0,0 +1,777 @@
1
+ """
2
+ Platform Service Component for Solace Agent Mesh.
3
+ Hosts the FastAPI REST API server for platform configuration management.
4
+ """
5
+
6
+ import logging
7
+ import threading
8
+ import json
9
+ from typing import Any, Dict
10
+
11
+ import uvicorn
12
+ from solace_ai_connector.common.message import Message as SolaceMessage
13
+ from solace_agent_mesh.common.sac.sam_component_base import SamComponentBase
14
+ from solace_agent_mesh.common.middleware.config_resolver import ConfigResolver
15
+ from solace_agent_mesh.core_a2a.service import CoreA2AService
16
+ from solace_agent_mesh.common import a2a
17
+ from solace_agent_mesh.common.constants import (
18
+ HEALTH_CHECK_INTERVAL_SECONDS,
19
+ HEALTH_CHECK_TTL_SECONDS,
20
+ )
21
+ from a2a.types import AgentCard
22
+
23
+ log = logging.getLogger(__name__)
24
+
25
+
26
+ class _StubSessionManager:
27
+ """
28
+ Minimal stub for SessionManager to satisfy legacy router dependencies.
29
+
30
+ Platform service doesn't have chat sessions, but webui_backend routers
31
+ (originally designed for WebUI gateway) expect a SessionManager.
32
+ This stub provides minimal compatibility.
33
+ """
34
+ pass
35
+
36
+
37
+ info = {
38
+ "class_name": "PlatformServiceComponent",
39
+ "description": (
40
+ "Platform Service Component - REST API for platform management (agents, connectors, deployments). "
41
+ "This is a SERVICE, not a gateway - services provide internal platform functionality, "
42
+ "while gateways handle external communication channels."
43
+ ),
44
+ }
45
+
46
+
47
+ class PlatformServiceComponent(SamComponentBase):
48
+ """
49
+ Platform Service Component - Management plane for SAM platform.
50
+
51
+ Architecture distinction:
52
+ - SERVICE: Provides internal platform functionality (this component)
53
+ - GATEWAY: Handles external communication channels (http_sse, slack, webhook, etc.)
54
+
55
+ Responsibilities:
56
+ - REST API for platform configuration management
57
+ - Agent Builder CRUD operations
58
+ - Connector management
59
+ - Deployment orchestration
60
+ - Deployer heartbeat monitoring
61
+ - Background deployment status checking
62
+
63
+ Key characteristics:
64
+ - No user chat sessions (services don't interact with end users)
65
+ - Uses direct messaging (publishes commands to deployer, receives heartbeats)
66
+ - Has agent registry (for deployment monitoring, not chat orchestration)
67
+ - Independent from WebUI gateway
68
+ - NOT A2A communication (deployer is a service, not an agent)
69
+ """
70
+
71
+ HEALTH_CHECK_TIMER_ID = "platform_agent_health_check"
72
+
73
+ def get_config(self, key: str, default: Any = None) -> Any:
74
+ """
75
+ Override get_config to look inside nested 'app_config' dictionary.
76
+
77
+ PlatformServiceApp places configuration in component_config['app_config'],
78
+ following the same pattern as BaseGatewayApp.
79
+
80
+ Args:
81
+ key: Configuration key to retrieve
82
+ default: Default value if key not found
83
+
84
+ Returns:
85
+ Configuration value or default
86
+ """
87
+ if "app_config" in self.component_config:
88
+ value = self.component_config["app_config"].get(key)
89
+ if value is not None:
90
+ return value
91
+
92
+ return super().get_config(key, default)
93
+
94
+ def __init__(self, **kwargs):
95
+ """
96
+ Initialize the PlatformServiceComponent.
97
+
98
+ Retrieves configuration, initializes FastAPI server state,
99
+ and starts the FastAPI/Uvicorn server.
100
+ """
101
+ # Initialize SamComponentBase (provides namespace, max_message_size, async loop)
102
+ super().__init__(info, **kwargs)
103
+ log.info("%s Initializing Platform Service Component...", self.log_identifier)
104
+
105
+ # Note: self.namespace is already set by SamComponentBase
106
+ # Note: self.max_message_size_bytes is already set by SamComponentBase
107
+
108
+ try:
109
+ # Retrieve Platform Service specific configuration
110
+ self.database_url = self.get_config("database_url")
111
+ self.fastapi_host = self.get_config("fastapi_host", "127.0.0.1")
112
+ self.fastapi_port = int(self.get_config("fastapi_port", 8001))
113
+ self.fastapi_https_port = int(self.get_config("fastapi_https_port", 8444))
114
+ self.ssl_keyfile = self.get_config("ssl_keyfile", "")
115
+ self.ssl_certfile = self.get_config("ssl_certfile", "")
116
+ self.ssl_keyfile_password = self.get_config("ssl_keyfile_password", "")
117
+ self.cors_allowed_origins = self.get_config("cors_allowed_origins", ["*"])
118
+ self.cors_allowed_origin_regex = self.get_config("cors_allowed_origin_regex", "")
119
+
120
+ # OAuth2 configuration (enterprise feature - defaults to community mode)
121
+ self.external_auth_service_url = self.get_config("external_auth_service_url", "")
122
+ self.external_auth_provider = self.get_config("external_auth_provider", "generic")
123
+
124
+ # Background task configuration
125
+ self.deployment_timeout_minutes = self.get_config("deployment_timeout_minutes", 5)
126
+ self.heartbeat_timeout_seconds = self.get_config("heartbeat_timeout_seconds", 90)
127
+ self.deployment_check_interval_seconds = self.get_config("deployment_check_interval_seconds", 60)
128
+
129
+ # Agent health check configuration (for removing expired agents from registry)
130
+ self.health_check_interval_seconds = self.get_config(
131
+ "health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS
132
+ )
133
+ self.health_check_ttl_seconds = self.get_config(
134
+ "health_check_ttl_seconds", HEALTH_CHECK_TTL_SECONDS
135
+ )
136
+
137
+ log.info(
138
+ "%s Platform service configuration retrieved (Host: %s, Port: %d, Auth: %s).",
139
+ self.log_identifier,
140
+ self.fastapi_host,
141
+ self.fastapi_port,
142
+ "enabled" if self.get_config("frontend_use_authorization", False) else "disabled",
143
+ )
144
+ except Exception as e:
145
+ log.error("%s Failed to retrieve configuration: %s", self.log_identifier, e)
146
+ raise ValueError(f"Configuration retrieval error: {e}") from e
147
+
148
+ # FastAPI server state (initialized later)
149
+ self.fastapi_app = None
150
+ self.uvicorn_server = None
151
+ self.fastapi_thread = None
152
+
153
+ # Config resolver (permissive default - allows all features/scopes)
154
+ self.config_resolver = ConfigResolver()
155
+
156
+ # Legacy router compatibility
157
+ # webui_backend routers were originally designed for WebUI gateway context
158
+ # but now work with Platform Service via dependency abstraction
159
+ self.session_manager = _StubSessionManager()
160
+
161
+ # Agent discovery (like BaseGatewayComponent)
162
+ # Initialize here so CoreA2AService can use it
163
+ from solace_agent_mesh.common.agent_registry import AgentRegistry
164
+ self.agent_registry = AgentRegistry()
165
+ self.core_a2a_service = CoreA2AService(
166
+ agent_registry=self.agent_registry,
167
+ namespace=self.namespace,
168
+ component_id="Platform"
169
+ )
170
+ log.info("%s Agent discovery service initialized", self.log_identifier)
171
+
172
+ # Background task state (for heartbeat monitoring and deployment status checking)
173
+ # Note: agent_registry already initialized above
174
+ self.heartbeat_tracker = None
175
+ self.heartbeat_listener = None
176
+ self.background_scheduler = None
177
+ self.background_tasks_thread = None
178
+
179
+ self.direct_publisher = None
180
+
181
+ log.info("%s Running database migrations...", self.log_identifier)
182
+ self._run_database_migrations()
183
+ log.info("%s Database migrations completed", self.log_identifier)
184
+
185
+ log.info("%s Platform Service Component initialized.", self.log_identifier)
186
+
187
+ def _run_database_migrations(self):
188
+ """Run database migrations synchronously during __init__."""
189
+ try:
190
+ from .api.main import _setup_database
191
+ _setup_database(self.database_url)
192
+ except Exception as e:
193
+ log.error(
194
+ "%s Failed to run database migrations: %s",
195
+ self.log_identifier,
196
+ e,
197
+ exc_info=True
198
+ )
199
+ raise RuntimeError(f"Database migration failed during component initialization: {e}") from e
200
+
201
+ def _late_init(self):
202
+ """
203
+ Late initialization called by SamComponentBase.run() after broker is ready.
204
+
205
+ This is the proper place to initialize services that require broker connectivity:
206
+ - FastAPI server (with startup event for background tasks)
207
+ - Direct message publisher (for deployer commands)
208
+ - Agent health check timer (for removing expired agents from registry)
209
+ """
210
+ log.info("%s Starting late initialization (broker-dependent services)...", self.log_identifier)
211
+
212
+ # Initialize direct message publisher for deployer commands
213
+ self._init_direct_publisher()
214
+
215
+ # Start FastAPI server (background tasks started via FastAPI startup event)
216
+ self._start_fastapi_server()
217
+
218
+ # Schedule agent health checks to remove expired agents from registry
219
+ self._schedule_agent_health_check()
220
+
221
+ log.info("%s Late initialization complete", self.log_identifier)
222
+
223
+ def _start_fastapi_server(self):
224
+ """
225
+ Start the FastAPI/Uvicorn server in a separate background thread.
226
+
227
+ This method:
228
+ 1. Runs enterprise platform migrations if available
229
+ 2. Imports the FastAPI app and setup function
230
+ 3. Calls setup_dependencies to initialize DB, middleware, and routers
231
+ 4. Creates uvicorn.Config and uvicorn.Server
232
+ 5. Starts the server in a daemon thread
233
+ """
234
+ log.info(
235
+ "%s Attempting to start FastAPI/Uvicorn server...",
236
+ self.log_identifier,
237
+ )
238
+
239
+ if self.fastapi_thread and self.fastapi_thread.is_alive():
240
+ log.warning(
241
+ "%s FastAPI server thread already started.", self.log_identifier
242
+ )
243
+ return
244
+
245
+ try:
246
+ # Import FastAPI app and setup function
247
+ from .api.main import app as fastapi_app_instance
248
+ from .api.main import setup_dependencies
249
+
250
+ self.fastapi_app = fastapi_app_instance
251
+
252
+ setup_dependencies(self)
253
+
254
+ # Register startup event for background tasks
255
+ @self.fastapi_app.on_event("startup")
256
+ async def start_background_tasks():
257
+ try:
258
+ from solace_agent_mesh_enterprise.init_enterprise import start_platform_background_tasks
259
+
260
+ log.info("%s Starting enterprise platform background tasks...", self.log_identifier)
261
+ await start_platform_background_tasks(self)
262
+ log.info("%s Enterprise platform background tasks started", self.log_identifier)
263
+ except ImportError:
264
+ log.info(
265
+ "%s Enterprise package not available - no background tasks to start",
266
+ self.log_identifier
267
+ )
268
+ except Exception as e:
269
+ log.error(
270
+ "%s Failed to start enterprise background tasks: %s",
271
+ self.log_identifier,
272
+ e,
273
+ exc_info=True
274
+ )
275
+
276
+ # Determine port based on SSL configuration
277
+ port = (
278
+ self.fastapi_https_port
279
+ if self.ssl_keyfile and self.ssl_certfile
280
+ else self.fastapi_port
281
+ )
282
+
283
+ # Create uvicorn configuration with SSL support
284
+ config = uvicorn.Config(
285
+ app=self.fastapi_app,
286
+ host=self.fastapi_host,
287
+ port=port,
288
+ log_level="warning",
289
+ lifespan="on",
290
+ ssl_keyfile=self.ssl_keyfile if self.ssl_keyfile else None,
291
+ ssl_certfile=self.ssl_certfile if self.ssl_certfile else None,
292
+ ssl_keyfile_password=self.ssl_keyfile_password if self.ssl_keyfile_password else None,
293
+ log_config=None,
294
+ )
295
+ self.uvicorn_server = uvicorn.Server(config)
296
+
297
+ # Start server in background thread
298
+ self.fastapi_thread = threading.Thread(
299
+ target=self.uvicorn_server.run,
300
+ daemon=True,
301
+ name="PlatformService_FastAPI_Thread",
302
+ )
303
+ self.fastapi_thread.start()
304
+
305
+ # Log with correct protocol
306
+ protocol = "https" if self.ssl_keyfile and self.ssl_certfile else "http"
307
+ log.info(
308
+ "%s FastAPI/Uvicorn server starting in background thread on %s://%s:%d",
309
+ self.log_identifier,
310
+ protocol,
311
+ self.fastapi_host,
312
+ port,
313
+ )
314
+
315
+ except Exception as e:
316
+ log.error(
317
+ "%s Failed to start FastAPI/Uvicorn server: %s",
318
+ self.log_identifier,
319
+ e,
320
+ )
321
+ raise
322
+
323
+ def _init_direct_publisher(self):
324
+ """
325
+ Initialize direct message publisher for deployer communication.
326
+
327
+ Platform Service sends deployment commands directly to deployer:
328
+ - {namespace}/deployer/agent/{id}/deploy
329
+ - {namespace}/deployer/agent/{id}/update
330
+ - {namespace}/deployer/agent/{id}/undeploy
331
+
332
+ Uses direct publishing (not A2A protocol) since deployer is a
333
+ standalone service, not an A2A agent.
334
+
335
+ Called from _late_init() and lazily from publish_a2a() if needed.
336
+ Uses SAC's existing broker connection via the BrokerOutput component.
337
+ """
338
+ try:
339
+ main_app = self.get_app()
340
+ if not main_app or not main_app.flows:
341
+ log.info(
342
+ "%s App flows not yet available - direct publisher will be initialized later",
343
+ self.log_identifier
344
+ )
345
+ return
346
+
347
+ # Find BrokerOutput component in the flow (same pattern as App.send_message)
348
+ broker_output = None
349
+ flow = main_app.flows[0]
350
+ if flow.component_groups:
351
+ for group in reversed(flow.component_groups):
352
+ if group:
353
+ comp = group[0]
354
+ if comp.module_info.get("class_name") == "BrokerOutput":
355
+ broker_output = comp
356
+ break
357
+
358
+ if not broker_output or not hasattr(broker_output, 'messaging_service'):
359
+ log.info(
360
+ "%s BrokerOutput component not ready - direct publisher will be initialized later",
361
+ self.log_identifier
362
+ )
363
+ return
364
+
365
+ self._messaging_service = broker_output.messaging_service.messaging_service
366
+ self.direct_publisher = self._messaging_service.create_direct_message_publisher_builder().build()
367
+ self.direct_publisher.start()
368
+
369
+ log.info("%s Direct message publisher initialized for deployer commands", self.log_identifier)
370
+
371
+ except Exception as e:
372
+ log.warning(
373
+ "%s Could not initialize direct publisher: %s (deployment commands will not work)",
374
+ self.log_identifier,
375
+ e
376
+ )
377
+
378
+ async def _handle_message_async(self, message, topic: str) -> None:
379
+ """
380
+ Handle incoming broker messages asynchronously (required by SamComponentBase).
381
+
382
+ Processes agent discovery messages and updates AgentRegistry.
383
+
384
+ Args:
385
+ message: The broker message
386
+ topic: The topic the message was received on
387
+ """
388
+ log.debug(
389
+ "%s Received async message on topic: %s",
390
+ self.log_identifier,
391
+ topic,
392
+ )
393
+
394
+ processed_successfully = False
395
+
396
+ try:
397
+ if a2a.topic_matches_subscription(
398
+ topic, a2a.get_discovery_topic(self.namespace)
399
+ ):
400
+ payload = message.get_payload()
401
+
402
+ # Parse JSON if payload is string/bytes (defensive coding)
403
+ if isinstance(payload, bytes):
404
+ payload = json.loads(payload.decode('utf-8'))
405
+ elif isinstance(payload, str):
406
+ payload = json.loads(payload)
407
+ # else: payload is already a dict (SAC framework auto-parses)
408
+
409
+ processed_successfully = self._handle_discovery_message(payload)
410
+ else:
411
+ log.debug(
412
+ "%s Ignoring message on non-discovery topic: %s",
413
+ self.log_identifier,
414
+ topic,
415
+ )
416
+ processed_successfully = True
417
+
418
+ except Exception as e:
419
+ log.error(
420
+ "%s Error handling async message on topic %s: %s",
421
+ self.log_identifier,
422
+ topic,
423
+ e,
424
+ exc_info=True
425
+ )
426
+ processed_successfully = False
427
+ finally:
428
+ # Acknowledge message (like BaseGatewayComponent pattern)
429
+ if hasattr(message, 'call_acknowledgements'):
430
+ try:
431
+ if processed_successfully:
432
+ message.call_acknowledgements()
433
+ else:
434
+ message.call_negative_acknowledgements()
435
+ except Exception as ack_error:
436
+ log.warning(
437
+ "%s Error acknowledging message: %s",
438
+ self.log_identifier,
439
+ ack_error
440
+ )
441
+
442
+ def _handle_discovery_message(self, payload: Dict) -> bool:
443
+ """
444
+ Handle incoming agent discovery messages.
445
+
446
+ Follows the same pattern as BaseGatewayComponent for consistency.
447
+
448
+ Args:
449
+ payload: The message payload dictionary
450
+
451
+ Returns:
452
+ True if processed successfully, False otherwise
453
+ """
454
+ try:
455
+ agent_card = AgentCard(**payload)
456
+ self.core_a2a_service.process_discovery_message(agent_card)
457
+ log.debug(
458
+ "%s Processed agent discovery: %s",
459
+ self.log_identifier,
460
+ agent_card.name
461
+ )
462
+ return True
463
+ except Exception as e:
464
+ log.error(
465
+ "%s Failed to process discovery message: %s. Payload: %s",
466
+ self.log_identifier,
467
+ e,
468
+ payload,
469
+ exc_info=True
470
+ )
471
+ return False
472
+
473
+ def _get_component_id(self) -> str:
474
+ """
475
+ Return unique identifier for this component (required by SamComponentBase).
476
+
477
+ Returns:
478
+ Component identifier string
479
+ """
480
+ return "platform_service"
481
+
482
+ def _get_component_type(self) -> str:
483
+ """
484
+ Return component type (required by SamComponentBase).
485
+
486
+ Returns:
487
+ Component type string
488
+ """
489
+ return "service"
490
+
491
+ def _pre_async_cleanup(self) -> None:
492
+ """
493
+ Cleanup before async operations stop (required by SamComponentBase).
494
+
495
+ Platform Service doesn't have async-specific resources to clean up here.
496
+ Main cleanup happens in cleanup() method.
497
+ """
498
+ pass
499
+
500
+ def cleanup(self):
501
+ """
502
+ Gracefully shut down the Platform Service Component.
503
+
504
+ This method:
505
+ 1. Stops direct message publisher
506
+ 2. Stops background tasks (heartbeat listener, deployment checker)
507
+ 3. Stops agent registry
508
+ 4. Signals the uvicorn server to exit
509
+ 5. Waits for the FastAPI thread to finish
510
+ 6. Calls parent cleanup
511
+ """
512
+ log.info("%s Cleaning up Platform Service Component...", self.log_identifier)
513
+
514
+ # Stop direct publisher
515
+ if self.direct_publisher:
516
+ try:
517
+ self.direct_publisher.terminate()
518
+ log.info("%s Direct message publisher stopped", self.log_identifier)
519
+ except Exception as e:
520
+ log.warning("%s Error stopping direct publisher: %s", self.log_identifier, e)
521
+
522
+ # Stop background scheduler
523
+ if self.background_scheduler:
524
+ try:
525
+ import asyncio
526
+ loop = asyncio.new_event_loop()
527
+ asyncio.set_event_loop(loop)
528
+ loop.run_until_complete(self.background_scheduler.stop())
529
+ log.info("%s Background scheduler stopped", self.log_identifier)
530
+ except Exception as e:
531
+ log.warning("%s Error stopping background scheduler: %s", self.log_identifier, e)
532
+
533
+ # Stop heartbeat listener
534
+ if self.heartbeat_listener:
535
+ try:
536
+ self.heartbeat_listener.stop()
537
+ log.info("%s Heartbeat listener stopped", self.log_identifier)
538
+ except Exception as e:
539
+ log.warning("%s Error stopping heartbeat listener: %s", self.log_identifier, e)
540
+
541
+ # Cancel health check timer before clearing registry
542
+ self.cancel_timer(self.HEALTH_CHECK_TIMER_ID)
543
+ log.info("%s Health check timer cancelled", self.log_identifier)
544
+
545
+ # Stop agent registry
546
+ if self.agent_registry:
547
+ try:
548
+ self.agent_registry.clear()
549
+ log.info("%s Agent registry stopped", self.log_identifier)
550
+ except Exception as e:
551
+ log.warning("%s Error stopping agent registry: %s", self.log_identifier, e)
552
+
553
+ # Signal uvicorn to shutdown
554
+ if self.uvicorn_server:
555
+ self.uvicorn_server.should_exit = True
556
+
557
+ # Wait for FastAPI thread to exit
558
+ if self.fastapi_thread and self.fastapi_thread.is_alive():
559
+ log.info(
560
+ "%s Waiting for FastAPI server thread to exit...", self.log_identifier
561
+ )
562
+ self.fastapi_thread.join(timeout=10)
563
+ if self.fastapi_thread.is_alive():
564
+ log.warning(
565
+ "%s FastAPI server thread did not exit gracefully.",
566
+ self.log_identifier,
567
+ )
568
+
569
+ # Call SamComponentBase cleanup (stops async loop and threads)
570
+ super().cleanup()
571
+ log.info("%s Platform Service Component cleanup finished.", self.log_identifier)
572
+
573
+ def get_cors_origins(self) -> list[str]:
574
+ """
575
+ Return the configured CORS allowed origins.
576
+
577
+ Returns:
578
+ List of allowed origin strings.
579
+ """
580
+ return self.cors_allowed_origins
581
+
582
+ def get_cors_origin_regex(self) -> str:
583
+ """
584
+ Return the configured CORS allowed origin regex pattern.
585
+
586
+ Returns:
587
+ Regex pattern string, or empty string if not configured.
588
+ """
589
+ return self.cors_allowed_origin_regex
590
+
591
+ def get_namespace(self) -> str:
592
+ """
593
+ Return the component's namespace.
594
+
595
+ Returns:
596
+ Namespace string.
597
+ """
598
+ return self.namespace
599
+
600
+ def get_config_resolver(self) -> ConfigResolver:
601
+ """
602
+ Return the ConfigResolver instance.
603
+
604
+ The default ConfigResolver is permissive and allows all features/scopes.
605
+ This enables webui_backend routers (which use ValidatedUserConfig) to work
606
+ in platform mode without custom authorization logic.
607
+
608
+ Returns:
609
+ ConfigResolver instance.
610
+ """
611
+ return self.config_resolver
612
+
613
+ def get_session_manager(self) -> _StubSessionManager:
614
+ """
615
+ Return the stub SessionManager.
616
+
617
+ Platform service doesn't have real session management, but returns a
618
+ minimal stub to satisfy gateway dependencies that expect SessionManager.
619
+
620
+ Returns:
621
+ Stub SessionManager instance.
622
+ """
623
+ return self.session_manager
624
+
625
+ def get_heartbeat_tracker(self):
626
+ """
627
+ Return the heartbeat tracker instance.
628
+
629
+ Used by deployer status endpoint to check if deployer is online.
630
+
631
+ Returns:
632
+ HeartbeatTracker instance if initialized, None otherwise.
633
+ """
634
+ return self.heartbeat_tracker
635
+
636
+ def get_agent_registry(self):
637
+ """
638
+ Return the agent registry instance.
639
+
640
+ Used for deployment status monitoring.
641
+
642
+ Returns:
643
+ AgentRegistry instance if initialized, None otherwise.
644
+ """
645
+ return self.agent_registry
646
+
647
+ def _schedule_agent_health_check(self):
648
+ """
649
+ Schedule periodic agent health checks to remove expired agents from registry.
650
+
651
+ This is essential for deployment status checking - when an agent is undeployed,
652
+ the deployment status checker needs to see the agent removed from the registry
653
+ to mark the undeploy as successful.
654
+ """
655
+ if self.health_check_interval_seconds > 0:
656
+ log.info(
657
+ "%s Scheduling agent health check every %d seconds (TTL: %d seconds)",
658
+ self.log_identifier,
659
+ self.health_check_interval_seconds,
660
+ self.health_check_ttl_seconds,
661
+ )
662
+ self.add_timer(
663
+ delay_ms=self.health_check_interval_seconds * 1000,
664
+ timer_id=self.HEALTH_CHECK_TIMER_ID,
665
+ interval_ms=self.health_check_interval_seconds * 1000,
666
+ callback=lambda timer_data: self._check_agent_health(),
667
+ )
668
+ else:
669
+ log.warning(
670
+ "%s Agent health check disabled (interval=%d). "
671
+ "Agents will not be automatically removed from registry when they stop sending heartbeats.",
672
+ self.log_identifier,
673
+ self.health_check_interval_seconds,
674
+ )
675
+
676
+ def _check_agent_health(self):
677
+ """
678
+ Check agent health and remove expired agents from registry.
679
+
680
+ Called periodically by the health check timer. Iterates through all
681
+ registered agents and removes any whose TTL has expired (i.e., they
682
+ haven't sent a heartbeat recently).
683
+ """
684
+ log.debug("%s Performing agent health check...", self.log_identifier)
685
+
686
+ agent_names = self.agent_registry.get_agent_names()
687
+ total_agents = len(agent_names)
688
+ agents_removed = 0
689
+
690
+ for agent_name in agent_names:
691
+ is_expired, time_since_last_seen = self.agent_registry.check_ttl_expired(
692
+ agent_name, self.health_check_ttl_seconds
693
+ )
694
+
695
+ if is_expired:
696
+ log.warning(
697
+ "%s Agent '%s' TTL expired (last seen: %d seconds ago, TTL: %d seconds). Removing from registry.",
698
+ self.log_identifier,
699
+ agent_name,
700
+ time_since_last_seen,
701
+ self.health_check_ttl_seconds,
702
+ )
703
+ self.agent_registry.remove_agent(agent_name)
704
+ agents_removed += 1
705
+
706
+ if agents_removed > 0:
707
+ log.info(
708
+ "%s Agent health check complete: %d/%d agents removed",
709
+ self.log_identifier,
710
+ agents_removed,
711
+ total_agents,
712
+ )
713
+ else:
714
+ log.debug(
715
+ "%s Agent health check complete: %d agents, all healthy",
716
+ self.log_identifier,
717
+ total_agents,
718
+ )
719
+
720
+ def publish_a2a(
721
+ self, topic: str, payload: dict, user_properties: dict | None = None
722
+ ):
723
+ """
724
+ Publish direct message to deployer (not A2A protocol).
725
+
726
+ Platform Service sends deployment commands directly to deployer service.
727
+ This is service-to-service communication, not agent-to-agent protocol.
728
+
729
+ Commands sent to:
730
+ - {namespace}/deployer/agent/{agent_id}/deploy
731
+ - {namespace}/deployer/agent/{agent_id}/update
732
+ - {namespace}/deployer/agent/{agent_id}/undeploy
733
+
734
+ Args:
735
+ topic: Message topic
736
+ payload: Message payload dictionary (will be JSON-serialized)
737
+ user_properties: Optional user properties (not used by deployer)
738
+
739
+ Raises:
740
+ Exception: If publishing fails
741
+ """
742
+ import json
743
+ from solace.messaging.resources.topic import Topic
744
+
745
+ log.debug("%s Publishing deployer command to topic: %s", self.log_identifier, topic)
746
+
747
+ try:
748
+ if not self.direct_publisher:
749
+ self._init_direct_publisher()
750
+ if not self.direct_publisher:
751
+ raise RuntimeError("Direct publisher not initialized")
752
+
753
+ # Serialize payload to JSON and convert to bytearray
754
+ message_body = json.dumps(payload)
755
+ message_bytes = bytearray(message_body.encode("utf-8"))
756
+
757
+ # Publish directly to topic
758
+ self.direct_publisher.publish(
759
+ message=message_bytes,
760
+ destination=Topic.of(topic)
761
+ )
762
+
763
+ log.debug(
764
+ "%s Successfully published deployer command to topic: %s (payload size: %d bytes)",
765
+ self.log_identifier,
766
+ topic,
767
+ len(message_body)
768
+ )
769
+
770
+ except Exception as e:
771
+ log.error(
772
+ "%s Failed to publish deployer command: %s",
773
+ self.log_identifier,
774
+ e,
775
+ exc_info=True
776
+ )
777
+ raise