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

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

Potentially problematic release.


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

Files changed (481) hide show
  1. solace_agent_mesh/agent/adk/alembic/README +74 -0
  2. solace_agent_mesh/agent/adk/alembic/env.py +77 -0
  3. solace_agent_mesh/agent/adk/alembic/script.py.mako +28 -0
  4. solace_agent_mesh/agent/adk/alembic/versions/e2902798564d_adk_session_db_upgrade.py +52 -0
  5. solace_agent_mesh/agent/adk/alembic.ini +112 -0
  6. solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
  7. solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +165 -1
  8. solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
  9. solace_agent_mesh/agent/adk/callbacks.py +852 -109
  10. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +234 -36
  11. solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +52 -5
  12. solace_agent_mesh/agent/adk/mcp_content_processor.py +1 -1
  13. solace_agent_mesh/agent/adk/models/lite_llm.py +77 -21
  14. solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
  15. solace_agent_mesh/agent/adk/runner.py +85 -20
  16. solace_agent_mesh/agent/adk/schema_migration.py +88 -0
  17. solace_agent_mesh/agent/adk/services.py +94 -18
  18. solace_agent_mesh/agent/adk/setup.py +281 -65
  19. solace_agent_mesh/agent/adk/stream_parser.py +231 -37
  20. solace_agent_mesh/agent/adk/tool_wrapper.py +3 -0
  21. solace_agent_mesh/agent/protocol/event_handlers.py +472 -137
  22. solace_agent_mesh/agent/proxies/a2a/app.py +3 -2
  23. solace_agent_mesh/agent/proxies/a2a/component.py +572 -75
  24. solace_agent_mesh/agent/proxies/a2a/config.py +80 -4
  25. solace_agent_mesh/agent/proxies/base/app.py +3 -2
  26. solace_agent_mesh/agent/proxies/base/component.py +188 -22
  27. solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
  28. solace_agent_mesh/agent/sac/app.py +91 -3
  29. solace_agent_mesh/agent/sac/component.py +591 -157
  30. solace_agent_mesh/agent/sac/patch_adk.py +8 -16
  31. solace_agent_mesh/agent/sac/task_execution_context.py +146 -4
  32. solace_agent_mesh/agent/tools/__init__.py +3 -0
  33. solace_agent_mesh/agent/tools/audio_tools.py +3 -3
  34. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +710 -171
  35. solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
  36. solace_agent_mesh/agent/tools/dynamic_tool.py +2 -0
  37. solace_agent_mesh/agent/tools/peer_agent_tool.py +82 -15
  38. solace_agent_mesh/agent/tools/time_tools.py +126 -0
  39. solace_agent_mesh/agent/tools/tool_config_types.py +57 -2
  40. solace_agent_mesh/agent/tools/web_search_tools.py +279 -0
  41. solace_agent_mesh/agent/tools/web_tools.py +125 -17
  42. solace_agent_mesh/agent/utils/artifact_helpers.py +248 -6
  43. solace_agent_mesh/agent/utils/context_helpers.py +17 -0
  44. solace_agent_mesh/assets/docs/404.html +6 -6
  45. solace_agent_mesh/assets/docs/assets/css/{styles.906a1503.css → styles.8162edfb.css} +1 -1
  46. solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
  47. solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/17896441.e612dfb4.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
  51. solace_agent_mesh/assets/docs/assets/js/{17896441.a5e82f9b.js.LICENSE.txt → 2279.550aa580.js.LICENSE.txt} +6 -0
  52. solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
  53. solace_agent_mesh/assets/docs/assets/js/2987107d.a80604f9.js +1 -0
  54. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
  55. solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
  56. solace_agent_mesh/assets/docs/assets/js/3ac1795d.7f7ab1c1.js +1 -0
  57. solace_agent_mesh/assets/docs/assets/js/3ff0015d.e53c9b78.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/41adc471.0e95b87c.js +1 -0
  59. solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
  60. solace_agent_mesh/assets/docs/assets/js/49eed117.493d6f99.js +1 -0
  61. solace_agent_mesh/assets/docs/assets/js/{509e993c.4c7a1a6d.js → 509e993c.a1fbf45a.js} +1 -1
  62. solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
  63. solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.js +1 -0
  64. solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
  65. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
  66. solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
  67. solace_agent_mesh/assets/docs/assets/js/631738c7.fa471607.js +1 -0
  68. solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
  69. solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
  70. solace_agent_mesh/assets/docs/assets/js/6a520c9d.b6e3f2ce.js +1 -0
  71. solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
  72. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.a5b36a60.js +1 -0
  73. solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
  74. solace_agent_mesh/assets/docs/assets/js/71da7b71.374b9d54.js +1 -0
  75. solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
  76. solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
  77. solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
  78. solace_agent_mesh/assets/docs/assets/js/81a99df0.7ed65d45.js +1 -0
  79. solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
  80. solace_agent_mesh/assets/docs/assets/js/8b032486.91a91afc.js +1 -0
  81. solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
  82. solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.js +1 -0
  83. solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
  84. solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
  85. solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
  86. solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
  87. solace_agent_mesh/assets/docs/assets/js/ad87452a.9d73dad6.js +1 -0
  88. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
  89. solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
  90. solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
  91. solace_agent_mesh/assets/docs/assets/js/da0b5bad.b62f7b08.js +1 -0
  92. solace_agent_mesh/assets/docs/assets/js/dd817ffc.c37a755e.js +1 -0
  93. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.b682e9c2.js +1 -0
  94. solace_agent_mesh/assets/docs/assets/js/de915948.44a432bc.js +1 -0
  95. solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
  96. solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
  97. solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
  98. solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
  99. solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
  100. solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
  101. solace_agent_mesh/assets/docs/assets/js/f284c35a.cc97854c.js +1 -0
  102. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.74710fc1.js +1 -0
  103. solace_agent_mesh/assets/docs/assets/js/main.d634009f.js +2 -0
  104. solace_agent_mesh/assets/docs/assets/js/runtime~main.27bb82a7.js +1 -0
  105. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +68 -68
  106. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +50 -50
  107. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +42 -42
  108. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +55 -55
  109. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +82 -68
  110. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
  111. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +67 -50
  112. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/research-tools/index.html +136 -0
  113. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +178 -144
  114. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +43 -42
  115. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +20 -18
  116. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +23 -23
  117. solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
  118. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +45 -45
  119. solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +182 -0
  120. solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
  121. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +208 -125
  122. solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
  123. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +28 -49
  124. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -30
  125. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +14 -14
  126. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/index.html +47 -0
  127. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
  128. solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +90 -0
  129. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -16
  130. solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
  131. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +38 -38
  132. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +162 -171
  133. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +67 -49
  134. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +17 -17
  135. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +51 -51
  136. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +22 -22
  137. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +27 -27
  138. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +135 -135
  139. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +66 -66
  140. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +51 -51
  141. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +50 -38
  142. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +86 -86
  143. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +51 -51
  144. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +24 -24
  145. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +30 -30
  146. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +44 -44
  147. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
  148. solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +86 -0
  149. solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +67 -0
  150. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +23 -19
  151. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +40 -37
  152. solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
  153. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +112 -87
  154. solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +440 -0
  155. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +87 -64
  156. solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +62 -0
  157. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +44 -44
  158. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +39 -37
  159. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +30 -30
  160. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +18 -18
  161. solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
  162. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +311 -0
  163. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +39 -42
  164. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +14 -14
  165. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +27 -25
  166. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +69 -69
  167. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +72 -72
  168. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +251 -0
  169. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +88 -0
  170. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +42 -42
  171. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +20 -20
  172. solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
  173. solace_agent_mesh/assets/docs/lunr-index-1768329217460.json +1 -0
  174. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  175. solace_agent_mesh/assets/docs/search-doc-1768329217460.json +1 -0
  176. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  177. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  178. solace_agent_mesh/cli/__init__.py +1 -1
  179. solace_agent_mesh/cli/commands/add_cmd/__init__.py +3 -1
  180. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +6 -1
  181. solace_agent_mesh/cli/commands/add_cmd/proxy_cmd.py +100 -0
  182. solace_agent_mesh/cli/commands/docs_cmd.py +4 -1
  183. solace_agent_mesh/cli/commands/eval_cmd.py +1 -1
  184. solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
  185. solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
  186. solace_agent_mesh/cli/commands/init_cmd/env_step.py +30 -3
  187. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +3 -4
  188. solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
  189. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +16 -3
  190. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +2 -1
  191. solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
  192. solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +3 -3
  193. solace_agent_mesh/cli/commands/run_cmd.py +64 -49
  194. solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
  195. solace_agent_mesh/cli/main.py +15 -0
  196. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-BTf6dqwp.js → authCallback-KnKMP_vb.js} +1 -1
  197. solace_agent_mesh/client/webui/frontend/static/assets/client-DpBL2stg.js +25 -0
  198. solace_agent_mesh/client/webui/frontend/static/assets/main-Cd498TV2.js +435 -0
  199. solace_agent_mesh/client/webui/frontend/static/assets/main-rSf8Vu29.css +1 -0
  200. solace_agent_mesh/client/webui/frontend/static/assets/vendor-CGk8Suyh.js +565 -0
  201. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  202. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  203. solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
  204. solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
  205. solace_agent_mesh/common/a2a/events.py +2 -1
  206. solace_agent_mesh/common/a2a/protocol.py +5 -0
  207. solace_agent_mesh/common/a2a/types.py +2 -1
  208. solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +23 -6
  209. solace_agent_mesh/common/a2a_spec/schemas/feedback_event.json +51 -0
  210. solace_agent_mesh/common/agent_registry.py +38 -11
  211. solace_agent_mesh/common/data_parts.py +144 -4
  212. solace_agent_mesh/common/error_handlers.py +83 -0
  213. solace_agent_mesh/common/exceptions.py +24 -0
  214. solace_agent_mesh/common/oauth/__init__.py +17 -0
  215. solace_agent_mesh/common/oauth/oauth_client.py +408 -0
  216. solace_agent_mesh/common/oauth/utils.py +50 -0
  217. solace_agent_mesh/common/rag_dto.py +156 -0
  218. solace_agent_mesh/common/sac/sam_component_base.py +97 -19
  219. solace_agent_mesh/common/sam_events/event_service.py +2 -2
  220. solace_agent_mesh/common/services/employee_service.py +1 -1
  221. solace_agent_mesh/common/utils/embeds/constants.py +1 -0
  222. solace_agent_mesh/common/utils/embeds/converter.py +1 -8
  223. solace_agent_mesh/common/utils/embeds/modifiers.py +4 -28
  224. solace_agent_mesh/common/utils/embeds/resolver.py +152 -31
  225. solace_agent_mesh/common/utils/embeds/types.py +9 -0
  226. solace_agent_mesh/common/utils/log_formatters.py +20 -0
  227. solace_agent_mesh/common/utils/mime_helpers.py +12 -5
  228. solace_agent_mesh/common/utils/pydantic_utils.py +90 -3
  229. solace_agent_mesh/common/utils/rbac_utils.py +69 -0
  230. solace_agent_mesh/common/utils/templates/__init__.py +8 -0
  231. solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
  232. solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
  233. solace_agent_mesh/config_portal/backend/common.py +12 -0
  234. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-CljP4_mv.js +103 -0
  235. solace_agent_mesh/config_portal/frontend/static/client/assets/{components-Rk0n-9cK.js → components-CaC6hG8d.js} +22 -22
  236. solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-mvZjNKiz.js → entry.client-H_TM0YBt.js} +3 -3
  237. solace_agent_mesh/config_portal/frontend/static/client/assets/{index-DzNKzXrc.js → index-CnFykb2v.js} +16 -16
  238. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-f8439d40.js +1 -0
  239. solace_agent_mesh/config_portal/frontend/static/client/assets/root-BIMqslJB.css +1 -0
  240. solace_agent_mesh/config_portal/frontend/static/client/assets/root-mJmTIdIk.js +10 -0
  241. solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
  242. solace_agent_mesh/core_a2a/service.py +3 -2
  243. solace_agent_mesh/gateway/adapter/__init__.py +1 -0
  244. solace_agent_mesh/gateway/adapter/base.py +170 -0
  245. solace_agent_mesh/gateway/adapter/types.py +230 -0
  246. solace_agent_mesh/gateway/base/app.py +39 -2
  247. solace_agent_mesh/gateway/base/auth_interface.py +103 -0
  248. solace_agent_mesh/gateway/base/component.py +1027 -151
  249. solace_agent_mesh/gateway/generic/__init__.py +1 -0
  250. solace_agent_mesh/gateway/generic/app.py +50 -0
  251. solace_agent_mesh/gateway/generic/component.py +894 -0
  252. solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
  253. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_project_users_table.py +72 -0
  254. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +109 -0
  255. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +26 -0
  256. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_projects_table.py +135 -0
  257. solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
  258. solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
  259. solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
  260. solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
  261. solace_agent_mesh/gateway/http_sse/alembic.ini +0 -36
  262. solace_agent_mesh/gateway/http_sse/app.py +40 -11
  263. solace_agent_mesh/gateway/http_sse/component.py +285 -160
  264. solace_agent_mesh/gateway/http_sse/dependencies.py +149 -114
  265. solace_agent_mesh/gateway/http_sse/main.py +68 -450
  266. solace_agent_mesh/gateway/http_sse/repository/__init__.py +19 -1
  267. solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
  268. solace_agent_mesh/gateway/http_sse/repository/entities/project.py +81 -0
  269. solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +47 -0
  270. solace_agent_mesh/gateway/http_sse/repository/entities/session.py +26 -3
  271. solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
  272. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +47 -0
  273. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +114 -6
  274. solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +13 -0
  275. solace_agent_mesh/gateway/http_sse/repository/models/project_model.py +51 -0
  276. solace_agent_mesh/gateway/http_sse/repository/models/project_user_model.py +75 -0
  277. solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
  278. solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +8 -2
  279. solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
  280. solace_agent_mesh/gateway/http_sse/repository/project_repository.py +172 -0
  281. solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +186 -0
  282. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +177 -11
  283. solace_agent_mesh/gateway/http_sse/repository/task_repository.py +86 -2
  284. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +38 -7
  285. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +256 -58
  286. solace_agent_mesh/gateway/http_sse/routers/auth.py +168 -134
  287. solace_agent_mesh/gateway/http_sse/routers/config.py +302 -8
  288. solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
  289. solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
  290. solace_agent_mesh/gateway/http_sse/routers/dto/requests/project_requests.py +48 -0
  291. solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +14 -1
  292. solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
  293. solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +31 -0
  294. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +5 -2
  295. solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
  296. solace_agent_mesh/gateway/http_sse/routers/feedback.py +133 -2
  297. solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
  298. solace_agent_mesh/gateway/http_sse/routers/projects.py +768 -0
  299. solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
  300. solace_agent_mesh/gateway/http_sse/routers/sessions.py +167 -7
  301. solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
  302. solace_agent_mesh/gateway/http_sse/routers/sse.py +131 -8
  303. solace_agent_mesh/gateway/http_sse/routers/tasks.py +670 -18
  304. solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
  305. solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
  306. solace_agent_mesh/gateway/http_sse/routers/visualization.py +92 -9
  307. solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
  308. solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
  309. solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
  310. solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
  311. solace_agent_mesh/gateway/http_sse/services/project_service.py +930 -0
  312. solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
  313. solace_agent_mesh/gateway/http_sse/services/session_service.py +361 -12
  314. solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
  315. solace_agent_mesh/gateway/http_sse/session_manager.py +15 -15
  316. solace_agent_mesh/gateway/http_sse/sse_manager.py +286 -166
  317. solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
  318. solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +41 -1
  319. solace_agent_mesh/services/__init__.py +0 -0
  320. solace_agent_mesh/services/platform/__init__.py +29 -0
  321. solace_agent_mesh/services/platform/alembic/env.py +85 -0
  322. solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
  323. solace_agent_mesh/services/platform/alembic.ini +109 -0
  324. solace_agent_mesh/services/platform/api/__init__.py +3 -0
  325. solace_agent_mesh/services/platform/api/dependencies.py +154 -0
  326. solace_agent_mesh/services/platform/api/main.py +314 -0
  327. solace_agent_mesh/services/platform/api/middleware.py +51 -0
  328. solace_agent_mesh/services/platform/api/routers/__init__.py +33 -0
  329. solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
  330. solace_agent_mesh/services/platform/app.py +215 -0
  331. solace_agent_mesh/services/platform/component.py +777 -0
  332. solace_agent_mesh/shared/__init__.py +14 -0
  333. solace_agent_mesh/shared/api/__init__.py +42 -0
  334. solace_agent_mesh/shared/auth/__init__.py +26 -0
  335. solace_agent_mesh/shared/auth/dependencies.py +204 -0
  336. solace_agent_mesh/shared/auth/middleware.py +347 -0
  337. solace_agent_mesh/shared/database/__init__.py +20 -0
  338. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
  339. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
  340. solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
  341. solace_agent_mesh/shared/exceptions/__init__.py +36 -0
  342. solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +19 -5
  343. solace_agent_mesh/shared/utils/__init__.py +21 -0
  344. solace_agent_mesh/templates/logging_config_template.yaml +48 -0
  345. solace_agent_mesh/templates/main_orchestrator.yaml +12 -1
  346. solace_agent_mesh/templates/platform.yaml +49 -0
  347. solace_agent_mesh/templates/plugin_readme_template.md +3 -25
  348. solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
  349. solace_agent_mesh/templates/proxy_template.yaml +62 -0
  350. solace_agent_mesh/templates/webui.yaml +148 -6
  351. solace_agent_mesh/tools/web_search/__init__.py +18 -0
  352. solace_agent_mesh/tools/web_search/base.py +84 -0
  353. solace_agent_mesh/tools/web_search/google_search.py +247 -0
  354. solace_agent_mesh/tools/web_search/models.py +99 -0
  355. {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +31 -12
  356. solace_agent_mesh-1.13.2.dist-info/RECORD +591 -0
  357. {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
  358. solace_agent_mesh/agent/adk/adk_llm.txt +0 -232
  359. solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
  360. solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
  361. solace_agent_mesh/agent/adk/models/models_llm.txt +0 -142
  362. solace_agent_mesh/agent/agent_llm.txt +0 -378
  363. solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
  364. solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
  365. solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
  366. solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
  367. solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
  368. solace_agent_mesh/agent/testing/testing_llm.txt +0 -57
  369. solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
  370. solace_agent_mesh/agent/tools/tools_llm.txt +0 -263
  371. solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -274
  372. solace_agent_mesh/agent/utils/utils_llm.txt +0 -138
  373. solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
  374. solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +0 -1
  375. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
  376. solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +0 -1
  377. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
  378. solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
  379. solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +0 -1
  380. solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +0 -1
  381. solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +0 -1
  382. solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
  383. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +0 -1
  384. solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +0 -1
  385. solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +0 -1
  386. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +0 -1
  387. solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
  388. solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +0 -1
  389. solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +0 -1
  390. solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +0 -1
  391. solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +0 -1
  392. solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +0 -1
  393. solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +0 -1
  394. solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +0 -1
  395. solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +0 -1
  396. solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e6dd091.js +0 -1
  397. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
  398. solace_agent_mesh/assets/docs/assets/js/da0b5bad.d08a9466.js +0 -1
  399. solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +0 -1
  400. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +0 -1
  401. solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +0 -1
  402. solace_agent_mesh/assets/docs/assets/js/e3d9abda.6b9493d0.js +0 -1
  403. solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +0 -1
  404. solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +0 -1
  405. solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +0 -1
  406. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +0 -1
  407. solace_agent_mesh/assets/docs/assets/js/main.b12eac43.js +0 -2
  408. solace_agent_mesh/assets/docs/assets/js/runtime~main.e268214e.js +0 -1
  409. solace_agent_mesh/assets/docs/lunr-index-1761248203150.json +0 -1
  410. solace_agent_mesh/assets/docs/search-doc-1761248203150.json +0 -1
  411. solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
  412. solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
  413. solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
  414. solace_agent_mesh/client/webui/frontend/static/assets/client-CaY59VuC.js +0 -25
  415. solace_agent_mesh/client/webui/frontend/static/assets/main-B32noGmR.js +0 -342
  416. solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +0 -1
  417. solace_agent_mesh/client/webui/frontend/static/assets/vendor-BEmvJSYz.js +0 -405
  418. solace_agent_mesh/common/a2a/a2a_llm.txt +0 -182
  419. solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
  420. solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -407
  421. solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
  422. solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -313
  423. solace_agent_mesh/common/common_llm.txt +0 -251
  424. solace_agent_mesh/common/common_llm_detail.txt +0 -2562
  425. solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
  426. solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
  427. solace_agent_mesh/common/sac/sac_llm.txt +0 -71
  428. solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
  429. solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
  430. solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
  431. solace_agent_mesh/common/services/providers/providers_llm.txt +0 -80
  432. solace_agent_mesh/common/services/services_llm.txt +0 -363
  433. solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
  434. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
  435. solace_agent_mesh/common/utils/utils_llm.txt +0 -336
  436. solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
  437. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +0 -98
  438. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-61038fc6.js +0 -1
  439. solace_agent_mesh/config_portal/frontend/static/client/assets/root-BWvk5-gF.js +0 -10
  440. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +0 -1
  441. solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
  442. solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
  443. solace_agent_mesh/gateway/base/base_llm.txt +0 -224
  444. solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
  445. solace_agent_mesh/gateway/gateway_llm.txt +0 -373
  446. solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
  447. solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -295
  448. solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -155
  449. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
  450. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
  451. solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
  452. solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -263
  453. solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -266
  454. solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -340
  455. solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -346
  456. solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -83
  457. solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -107
  458. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -314
  459. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -297
  460. solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
  461. solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -285
  462. solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
  463. solace_agent_mesh/llm.txt +0 -228
  464. solace_agent_mesh/llm_detail.txt +0 -2835
  465. solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
  466. solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
  467. solace_agent_mesh/templates/logging_config_template.ini +0 -45
  468. solace_agent_mesh/templates/templates_llm.txt +0 -147
  469. solace_agent_mesh-1.6.1.dist-info/RECORD +0 -525
  470. /solace_agent_mesh/assets/docs/assets/js/{main.b12eac43.js.LICENSE.txt → main.d634009f.js.LICENSE.txt} +0 -0
  471. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
  472. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
  473. /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
  474. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
  475. /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
  476. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
  477. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
  478. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
  479. /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
  480. {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
  481. {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,10 +1,11 @@
1
1
  """
2
2
  FastAPI router for managing session-specific artifacts via REST endpoints.
3
3
  """
4
+ from __future__ import annotations
4
5
 
5
6
  import logging
6
7
  from collections.abc import Callable
7
- from typing import TYPE_CHECKING, Any
8
+ from typing import TYPE_CHECKING, Any, Optional
8
9
 
9
10
  from fastapi import (
10
11
  APIRouter,
@@ -13,6 +14,7 @@ from fastapi import (
13
14
  Form,
14
15
  HTTPException,
15
16
  Path,
17
+ Query,
16
18
  UploadFile,
17
19
  status,
18
20
  Request as FastAPIRequest,
@@ -39,8 +41,11 @@ from ....common.utils.embeds import (
39
41
  evaluate_embed,
40
42
  resolve_embeds_recursively_in_string,
41
43
  )
44
+ from ....common.utils.embeds.types import ResolutionMode
42
45
  from ....common.utils.mime_helpers import is_text_based_mime_type
46
+ from ....common.utils.templates import resolve_template_blocks_in_string
43
47
  from ..dependencies import (
48
+ get_project_service_optional,
44
49
  ValidatedUserConfig,
45
50
  get_sac_component,
46
51
  get_session_validator,
@@ -50,6 +55,7 @@ from ..dependencies import (
50
55
  get_session_business_service_optional,
51
56
  get_db_optional,
52
57
  )
58
+ from ..services.project_service import ProjectService
53
59
 
54
60
 
55
61
  from ..session_manager import SessionManager
@@ -67,6 +73,7 @@ if TYPE_CHECKING:
67
73
 
68
74
  log = logging.getLogger(__name__)
69
75
 
76
+ LOAD_FILE_CHUNK_SIZE = 1024 * 1024 # 1MB chunks
70
77
 
71
78
  class ArtifactUploadResponse(BaseModel):
72
79
  """Response model for artifact upload with camelCase fields."""
@@ -85,6 +92,80 @@ class ArtifactUploadResponse(BaseModel):
85
92
  router = APIRouter()
86
93
 
87
94
 
95
+ def _resolve_storage_context(
96
+ session_id: str,
97
+ project_id: str | None,
98
+ user_id: str,
99
+ validate_session: Callable[[str, str], bool],
100
+ project_service: ProjectService | None,
101
+ log_prefix: str
102
+ ) -> tuple[str, str, str]:
103
+ """
104
+ Resolve storage context from session or project parameters.
105
+
106
+ Returns:
107
+ tuple: (storage_user_id, storage_session_id, context_type)
108
+
109
+ Raises:
110
+ HTTPException: If no valid context found
111
+ """
112
+ # Priority 1: Session context
113
+ if session_id and session_id.strip() and session_id not in ["null", "undefined"]:
114
+ if not validate_session(session_id, user_id):
115
+ log.warning("%s Session validation failed", log_prefix)
116
+ raise HTTPException(
117
+ status_code=status.HTTP_404_NOT_FOUND,
118
+ detail="Session not found or access denied.",
119
+ )
120
+ return user_id, session_id, "session"
121
+
122
+ # Priority 2: Project context (only if persistence is enabled)
123
+ elif project_id and project_id.strip() and project_id not in ["null", "undefined"]:
124
+ if project_service is None:
125
+ log.warning("%s Project context requested but persistence not enabled", log_prefix)
126
+ raise HTTPException(
127
+ status_code=status.HTTP_501_NOT_IMPLEMENTED,
128
+ detail="Project context requires database configuration.",
129
+ )
130
+
131
+ from ....gateway.http_sse.dependencies import SessionLocal
132
+
133
+ if SessionLocal is None:
134
+ log.warning("%s Project context requested but database not configured", log_prefix)
135
+ raise HTTPException(
136
+ status_code=status.HTTP_501_NOT_IMPLEMENTED,
137
+ detail="Project context requires database configuration.",
138
+ )
139
+
140
+ db = SessionLocal()
141
+ try:
142
+ project = project_service.get_project(db, project_id, user_id)
143
+ if not project:
144
+ log.warning("%s Project not found or access denied", log_prefix)
145
+ raise HTTPException(
146
+ status_code=status.HTTP_404_NOT_FOUND,
147
+ detail="Project not found or access denied.",
148
+ )
149
+ return project.user_id, f"project-{project_id}", "project"
150
+ except HTTPException:
151
+ raise
152
+ except Exception as e:
153
+ log.error("%s Error resolving project context: %s", log_prefix, e)
154
+ raise HTTPException(
155
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
156
+ detail="Failed to resolve project context"
157
+ )
158
+ finally:
159
+ db.close()
160
+
161
+ # No valid context
162
+ log.warning("%s No valid context found", log_prefix)
163
+ raise HTTPException(
164
+ status_code=status.HTTP_404_NOT_FOUND,
165
+ detail="No valid context provided.",
166
+ )
167
+
168
+
88
169
  @router.post(
89
170
  "/upload",
90
171
  status_code=status.HTTP_201_CREATED,
@@ -127,6 +208,7 @@ async def upload_artifact_with_session(
127
208
 
128
209
  # Handle session creation logic (matching chat API pattern)
129
210
  effective_session_id = None
211
+ is_new_session = False # Track if we created a new session
130
212
 
131
213
  # Use session ID from request body (matching sessionId pattern in session APIs)
132
214
  if sessionId and sessionId.strip():
@@ -135,6 +217,7 @@ async def upload_artifact_with_session(
135
217
  else:
136
218
  # Create new session when no sessionId provided (like chat does for new conversations)
137
219
  effective_session_id = session_manager.create_new_session_id(request)
220
+ is_new_session = True # Mark that we created this session
138
221
  log.info(
139
222
  "%sCreated new session for file upload: %s",
140
223
  log_prefix,
@@ -193,7 +276,8 @@ async def upload_artifact_with_session(
193
276
  )
194
277
 
195
278
  # Validate session (now that we have an effective_session_id)
196
- if not validate_session(effective_session_id, user_id):
279
+ # Skip validation if we just created the session to avoid race conditions
280
+ if not is_new_session and not validate_session(effective_session_id, user_id):
197
281
  log.warning(
198
282
  "%sSession validation failed for session: %s",
199
283
  log_prefix,
@@ -212,8 +296,78 @@ async def upload_artifact_with_session(
212
296
  )
213
297
 
214
298
  try:
215
- # Read and validate file content
216
- content_bytes = await upload_file.read()
299
+ # ===== VALIDATE FILE SIZE BEFORE READING =====
300
+ max_upload_size = component.get_config("gateway_max_upload_size_bytes")
301
+
302
+ # Check Content-Length header first (if available)
303
+ content_length = request.headers.get("content-length")
304
+ if content_length:
305
+ try:
306
+ file_size = int(content_length)
307
+
308
+ if file_size > max_upload_size:
309
+ error_msg = (
310
+ f"File upload rejected: size {file_size:,} bytes "
311
+ f"exceeds maximum {max_upload_size:,} bytes "
312
+ f"({file_size / (1024*1024):.2f} MB > {max_upload_size / (1024*1024):.2f} MB)"
313
+ )
314
+ log.warning("%s %s", log_prefix, error_msg)
315
+
316
+ raise HTTPException(
317
+ status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
318
+ detail=error_msg # Use string instead of dict
319
+ )
320
+ except ValueError:
321
+ log.warning("%s Invalid Content-Length header: %s", log_prefix, content_length)
322
+
323
+ # Validate file size by streaming through WITHOUT accumulating chunks in memory
324
+ chunk_size = LOAD_FILE_CHUNK_SIZE
325
+ total_bytes_read = 0
326
+
327
+ try:
328
+ # Step 1: Validate size by reading chunks (discard data, just count bytes)
329
+ while True:
330
+ chunk = await upload_file.read(chunk_size)
331
+ if not chunk:
332
+ break # End of file
333
+
334
+ total_bytes_read += len(chunk)
335
+
336
+ # Validate size during reading (fail fast)
337
+ if total_bytes_read > max_upload_size:
338
+ error_msg = (
339
+ f"File '{upload_file.filename}' rejected: size exceeds maximum {max_upload_size:,} bytes "
340
+ f"(read {total_bytes_read:,} bytes so far, "
341
+ f"{total_bytes_read / (1024*1024):.2f} MB > {max_upload_size / (1024*1024):.2f} MB)"
342
+ )
343
+ log.warning("%s %s", log_prefix, error_msg)
344
+
345
+ raise HTTPException(
346
+ status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
347
+ detail=error_msg
348
+ )
349
+
350
+ # Step 2: Size is valid - reset to beginning
351
+ await upload_file.seek(0)
352
+
353
+ # Step 3: Read all content at once
354
+ content_bytes = await upload_file.read()
355
+
356
+ log.debug(
357
+ "%s File validated (%d bytes) and loaded into memory",
358
+ log_prefix,
359
+ total_bytes_read
360
+ )
361
+
362
+ except HTTPException:
363
+ # Re-raise HTTP exceptions (size limit exceeded)
364
+ raise
365
+ except Exception as read_error:
366
+ log.exception("%s Error reading uploaded file: %s", log_prefix, read_error)
367
+ raise HTTPException(
368
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
369
+ detail="Failed to read uploaded file"
370
+ )
217
371
 
218
372
  mime_type = upload_file.content_type or "application/octet-stream"
219
373
  filename_clean = filename.strip()
@@ -245,6 +399,8 @@ async def upload_artifact_with_session(
245
399
 
246
400
  if error_type in ["invalid_filename", "empty_file"]:
247
401
  status_code = status.HTTP_400_BAD_REQUEST
402
+ elif error_type == "file_too_large":
403
+ status_code = status.HTTP_413_REQUEST_ENTITY_TOO_LARGE
248
404
  else:
249
405
  status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
250
406
 
@@ -310,33 +466,32 @@ async def upload_artifact_with_session(
310
466
  )
311
467
  async def list_artifact_versions(
312
468
  session_id: str = Path(
313
- ..., title="Session ID", description="The session ID to get artifacts from"
469
+ ..., title="Session ID", description="The session ID to get artifacts from (or 'null' for project context)"
314
470
  ),
315
471
  filename: str = Path(..., title="Filename", description="The name of the artifact"),
472
+ project_id: Optional[str] = Query(None, description="Project ID for project context"),
316
473
  artifact_service: BaseArtifactService = Depends(get_shared_artifact_service),
317
474
  user_id: str = Depends(get_user_id),
318
475
  validate_session: Callable[[str, str], bool] = Depends(get_session_validator),
319
476
  component: "WebUIBackendComponent" = Depends(get_sac_component),
477
+ project_service: ProjectService | None = Depends(get_project_service_optional),
320
478
  user_config: dict = Depends(ValidatedUserConfig(["tool:artifact:list"])),
321
479
  ):
322
480
  """
323
481
  Lists the available integer versions for a given artifact filename
324
- associated with the current user and session ID.
482
+ associated with the specified context (session or project).
325
483
  """
326
484
 
327
485
  log_prefix = f"[ArtifactRouter:ListVersions:{filename}] User={user_id}, Session={session_id} -"
328
486
  log.info("%s Request received.", log_prefix)
329
487
 
330
- # Validate session exists and belongs to user
331
- if not validate_session(session_id, user_id):
332
- log.warning("%s Session validation failed or access denied.", log_prefix)
333
- raise HTTPException(
334
- status_code=status.HTTP_404_NOT_FOUND,
335
- detail="Session not found or access denied.",
336
- )
488
+ # Resolve storage context
489
+ storage_user_id, storage_session_id, context_type = _resolve_storage_context(
490
+ session_id, project_id, user_id, validate_session, project_service, log_prefix
491
+ )
337
492
 
338
493
  if artifact_service is None:
339
- log.error("%s Artifact service is not configured or available.", log_prefix)
494
+ log.error("%s Artifact service not available.", log_prefix)
340
495
  raise HTTPException(
341
496
  status_code=status.HTTP_501_NOT_IMPLEMENTED,
342
497
  detail="Artifact service is not configured.",
@@ -356,10 +511,13 @@ async def list_artifact_versions(
356
511
  try:
357
512
  app_name = component.get_config("name", "A2A_WebUI_App")
358
513
 
514
+ log.info("%s Using %s context: storage_user_id=%s, storage_session_id=%s",
515
+ log_prefix, context_type, storage_user_id, storage_session_id)
516
+
359
517
  versions = await artifact_service.list_versions(
360
518
  app_name=app_name,
361
- user_id=user_id,
362
- session_id=session_id,
519
+ user_id=storage_user_id,
520
+ session_id=storage_session_id,
363
521
  filename=filename,
364
522
  )
365
523
  log.info("%s Found versions: %s", log_prefix, versions)
@@ -368,7 +526,7 @@ async def list_artifact_versions(
368
526
  log.warning("%s Artifact not found.", log_prefix)
369
527
  raise HTTPException(
370
528
  status_code=status.HTTP_404_NOT_FOUND,
371
- detail=f"Artifact '{filename}' not found for this session.",
529
+ detail=f"Artifact '{filename}' not found.",
372
530
  )
373
531
  except Exception as e:
374
532
  log.exception("%s Error listing artifact versions: %s", log_prefix, e)
@@ -392,35 +550,33 @@ async def list_artifact_versions(
392
550
  )
393
551
  async def list_artifacts(
394
552
  session_id: str = Path(
395
- ..., title="Session ID", description="The session ID to list artifacts for"
553
+ ..., title="Session ID", description="The session ID to list artifacts for (or 'null' for project context)"
396
554
  ),
555
+ project_id: Optional[str] = Query(None, description="Project ID for project context"),
397
556
  artifact_service: BaseArtifactService = Depends(get_shared_artifact_service),
398
557
  user_id: str = Depends(get_user_id),
399
558
  validate_session: Callable[[str, str], bool] = Depends(get_session_validator),
400
559
  component: "WebUIBackendComponent" = Depends(get_sac_component),
560
+ project_service: ProjectService | None = Depends(get_project_service_optional),
401
561
  user_config: dict = Depends(ValidatedUserConfig(["tool:artifact:list"])),
402
562
  ):
403
563
  """
404
564
  Lists detailed information (filename, size, type, modified date, uri)
405
- for all artifacts associated with the specified user and session ID
406
- by calling the artifact helper function.
565
+ for all artifacts associated with the specified context (session or project).
407
566
  """
408
567
 
409
568
  log_prefix = f"[ArtifactRouter:ListInfo] User={user_id}, Session={session_id} -"
410
569
  log.info("%s Request received.", log_prefix)
411
570
 
412
- # Validate session exists and belongs to user
413
- if not validate_session(session_id, user_id):
414
- log.warning(
415
- "%s Session validation failed for session_id=%s, user_id=%s",
416
- log_prefix,
417
- session_id,
418
- user_id,
419
- )
420
- raise HTTPException(
421
- status_code=status.HTTP_404_NOT_FOUND,
422
- detail="Session not found or access denied.",
571
+ # Resolve storage context (projects vs sessions). This allows for project artiacts
572
+ # to be listed before a session is created.
573
+ try:
574
+ storage_user_id, storage_session_id, context_type = _resolve_storage_context(
575
+ session_id, project_id, user_id, validate_session, project_service, log_prefix
423
576
  )
577
+ except HTTPException:
578
+ log.info("%s No valid context found, returning empty list", log_prefix)
579
+ return []
424
580
 
425
581
  if artifact_service is None:
426
582
  log.error("%s Artifact service is not configured or available.", log_prefix)
@@ -432,22 +588,21 @@ async def list_artifacts(
432
588
  try:
433
589
  app_name = component.get_config("name", "A2A_WebUI_App")
434
590
 
591
+ log.info("%s Using %s context: storage_user_id=%s, storage_session_id=%s",
592
+ log_prefix, context_type, storage_user_id, storage_session_id)
593
+
435
594
  artifact_info_list = await get_artifact_info_list(
436
595
  artifact_service=artifact_service,
437
596
  app_name=app_name,
438
- user_id=user_id,
439
- session_id=session_id,
597
+ user_id=storage_user_id,
598
+ session_id=storage_session_id,
440
599
  )
441
600
 
442
- log.info(
443
- "%s Returning %d artifact details.", log_prefix, len(artifact_info_list)
444
- )
601
+ log.info("%s Returning %d artifact details.", log_prefix, len(artifact_info_list))
445
602
  return artifact_info_list
446
603
 
447
604
  except Exception as e:
448
- log.exception(
449
- "%s Error retrieving artifact details via helper: %s", log_prefix, e
450
- )
605
+ log.exception("%s Error retrieving artifact details: %s", log_prefix, e)
451
606
  raise HTTPException(
452
607
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
453
608
  detail=f"Failed to retrieve artifact details: {str(e)}",
@@ -461,24 +616,31 @@ async def list_artifacts(
461
616
  )
462
617
  async def get_latest_artifact(
463
618
  session_id: str = Path(
464
- ..., title="Session ID", description="The session ID to get artifacts from"
619
+ ..., title="Session ID", description="The session ID to get artifacts from (or 'null' for project context)"
465
620
  ),
466
621
  filename: str = Path(..., title="Filename", description="The name of the artifact"),
622
+ project_id: Optional[str] = Query(None, description="Project ID for project context"),
467
623
  artifact_service: BaseArtifactService = Depends(get_shared_artifact_service),
468
624
  user_id: str = Depends(get_user_id),
469
625
  validate_session: Callable[[str, str], bool] = Depends(get_session_validator),
470
626
  component: "WebUIBackendComponent" = Depends(get_sac_component),
627
+ project_service: ProjectService | None = Depends(get_project_service_optional),
471
628
  user_config: dict = Depends(ValidatedUserConfig(["tool:artifact:load"])),
472
629
  ):
473
630
  """
474
631
  Retrieves the content of the latest version of the specified artifact
475
- associated with the current user and session ID.
632
+ associated with the specified context (session or project).
476
633
  """
477
634
  log_prefix = (
478
635
  f"[ArtifactRouter:GetLatest:{filename}] User={user_id}, Session={session_id} -"
479
636
  )
480
637
  log.info("%s Request received.", log_prefix)
481
638
 
639
+ # Resolve storage context
640
+ storage_user_id, storage_session_id, context_type = _resolve_storage_context(
641
+ session_id, project_id, user_id, validate_session, project_service, log_prefix
642
+ )
643
+
482
644
  if artifact_service is None:
483
645
  log.error("%s Artifact service is not configured or available.", log_prefix)
484
646
  raise HTTPException(
@@ -488,10 +650,14 @@ async def get_latest_artifact(
488
650
 
489
651
  try:
490
652
  app_name = component.get_config("name", "A2A_WebUI_App")
653
+
654
+ log.info("%s Using %s context: storage_user_id=%s, storage_session_id=%s",
655
+ log_prefix, context_type, storage_user_id, storage_session_id)
656
+
491
657
  artifact_part = await artifact_service.load_artifact(
492
658
  app_name=app_name,
493
- user_id=user_id,
494
- session_id=session_id,
659
+ user_id=storage_user_id,
660
+ session_id=storage_session_id,
495
661
  filename=filename,
496
662
  )
497
663
 
@@ -537,17 +703,32 @@ async def get_latest_artifact(
537
703
  context=context_for_resolver,
538
704
  resolver_func=evaluate_embed,
539
705
  types_to_resolve=LATE_EMBED_TYPES,
706
+ resolution_mode=ResolutionMode.RECURSIVE_ARTIFACT_CONTENT,
540
707
  log_identifier=f"{log_prefix}[RecursiveResolve]",
541
708
  config=config_for_resolver,
542
709
  max_depth=component.gateway_recursive_embed_depth,
543
710
  max_total_size=component.gateway_max_artifact_resolve_size_bytes,
544
711
  )
545
- data_bytes = resolved_content_string.encode("utf-8")
546
712
  log.info(
547
713
  "%s Recursive embed resolution complete. New size: %d bytes.",
548
714
  log_prefix,
549
- len(data_bytes),
715
+ len(resolved_content_string),
550
716
  )
717
+
718
+ # Also resolve any template blocks in the artifact
719
+ resolved_content_string = await resolve_template_blocks_in_string(
720
+ text=resolved_content_string,
721
+ artifact_service=artifact_service,
722
+ session_context=context_for_resolver["session_context"],
723
+ log_identifier=f"{log_prefix}[TemplateResolve]",
724
+ )
725
+ log.info(
726
+ "%s Template block resolution complete. Final size: %d bytes.",
727
+ log_prefix,
728
+ len(resolved_content_string),
729
+ )
730
+
731
+ data_bytes = resolved_content_string.encode("utf-8")
551
732
  except UnicodeDecodeError as ude:
552
733
  log.warning(
553
734
  "%s Failed to decode artifact for recursive resolution: %s. Serving original content.",
@@ -596,7 +777,7 @@ async def get_latest_artifact(
596
777
  )
597
778
  async def get_specific_artifact_version(
598
779
  session_id: str = Path(
599
- ..., title="Session ID", description="The session ID to get artifacts from"
780
+ ..., title="Session ID", description="The session ID to get artifacts from (or 'null' for project context)"
600
781
  ),
601
782
  filename: str = Path(..., title="Filename", description="The name of the artifact"),
602
783
  version: int | str = Path(
@@ -604,26 +785,25 @@ async def get_specific_artifact_version(
604
785
  title="Version",
605
786
  description="The specific version number to retrieve, or 'latest'",
606
787
  ),
788
+ project_id: Optional[str] = Query(None, description="Project ID for project context"),
607
789
  artifact_service: BaseArtifactService = Depends(get_shared_artifact_service),
608
790
  user_id: str = Depends(get_user_id),
609
791
  validate_session: Callable[[str, str], bool] = Depends(get_session_validator),
610
792
  component: "WebUIBackendComponent" = Depends(get_sac_component),
793
+ project_service: ProjectService | None = Depends(get_project_service_optional),
611
794
  user_config: dict = Depends(ValidatedUserConfig(["tool:artifact:load"])),
612
795
  ):
613
796
  """
614
797
  Retrieves the content of a specific version of the specified artifact
615
- associated with the current user and session ID.
798
+ associated with the specified context (session or project).
616
799
  """
617
800
  log_prefix = f"[ArtifactRouter:GetVersion:{filename} v{version}] User={user_id}, Session={session_id} -"
618
801
  log.info("%s Request received.", log_prefix)
619
802
 
620
- # Validate session exists and belongs to user
621
- if not validate_session(session_id, user_id):
622
- log.warning("%s Session validation failed or access denied.", log_prefix)
623
- raise HTTPException(
624
- status_code=status.HTTP_404_NOT_FOUND,
625
- detail="Session not found or access denied.",
626
- )
803
+ # Resolve storage context
804
+ storage_user_id, storage_session_id, context_type = _resolve_storage_context(
805
+ session_id, project_id, user_id, validate_session, project_service, log_prefix
806
+ )
627
807
 
628
808
  if artifact_service is None:
629
809
  log.error("%s Artifact service is not configured or available.", log_prefix)
@@ -635,11 +815,14 @@ async def get_specific_artifact_version(
635
815
  try:
636
816
  app_name = component.get_config("name", "A2A_WebUI_App")
637
817
 
818
+ log.info("%s Using %s context: storage_user_id=%s, storage_session_id=%s",
819
+ log_prefix, context_type, storage_user_id, storage_session_id)
820
+
638
821
  load_result = await load_artifact_content_or_metadata(
639
822
  artifact_service=artifact_service,
640
823
  app_name=app_name,
641
- user_id=user_id,
642
- session_id=session_id,
824
+ user_id=storage_user_id,
825
+ session_id=storage_session_id,
643
826
  filename=filename,
644
827
  version=version,
645
828
  load_metadata_only=False,
@@ -715,17 +898,32 @@ async def get_specific_artifact_version(
715
898
  context=context_for_resolver,
716
899
  resolver_func=evaluate_embed,
717
900
  types_to_resolve=LATE_EMBED_TYPES,
901
+ resolution_mode=ResolutionMode.RECURSIVE_ARTIFACT_CONTENT,
718
902
  log_identifier=f"{log_prefix}[RecursiveResolve]",
719
903
  config=config_for_resolver,
720
904
  max_depth=component.gateway_recursive_embed_depth,
721
905
  max_total_size=component.gateway_max_artifact_resolve_size_bytes,
722
906
  )
723
- data_bytes = resolved_content_string.encode("utf-8")
724
907
  log.info(
725
908
  "%s Recursive embed resolution complete. New size: %d bytes.",
726
909
  log_prefix,
727
- len(data_bytes),
910
+ len(resolved_content_string),
911
+ )
912
+
913
+ # Also resolve any template blocks in the artifact
914
+ resolved_content_string = await resolve_template_blocks_in_string(
915
+ text=resolved_content_string,
916
+ artifact_service=artifact_service,
917
+ session_context=context_for_resolver["session_context"],
918
+ log_identifier=f"{log_prefix}[TemplateResolve]",
919
+ )
920
+ log.info(
921
+ "%s Template block resolution complete. Final size: %d bytes.",
922
+ log_prefix,
923
+ len(resolved_content_string),
728
924
  )
925
+
926
+ data_bytes = resolved_content_string.encode("utf-8")
729
927
  except UnicodeDecodeError as ude:
730
928
  log.warning(
731
929
  "%s Failed to decode artifact for recursive resolution: %s. Serving original content.",