solace-agent-mesh 1.6.3__py3-none-any.whl → 1.7.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (244) hide show
  1. solace_agent_mesh/agent/adk/adk_llm.txt +12 -18
  2. solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +1 -1
  3. solace_agent_mesh/agent/adk/callbacks.py +138 -20
  4. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +2 -0
  5. solace_agent_mesh/agent/adk/models/lite_llm.py +38 -5
  6. solace_agent_mesh/agent/adk/models/models_llm.txt +82 -35
  7. solace_agent_mesh/agent/adk/runner.py +9 -0
  8. solace_agent_mesh/agent/adk/stream_parser.py +6 -1
  9. solace_agent_mesh/agent/adk/tool_wrapper.py +3 -0
  10. solace_agent_mesh/agent/agent_llm.txt +61 -70
  11. solace_agent_mesh/agent/protocol/event_handlers.py +29 -1
  12. solace_agent_mesh/agent/protocol/protocol_llm.txt +1 -1
  13. solace_agent_mesh/agent/proxies/a2a/a2a_llm.txt +190 -0
  14. solace_agent_mesh/agent/proxies/base/base_llm.txt +148 -0
  15. solace_agent_mesh/agent/proxies/proxies_llm.txt +283 -0
  16. solace_agent_mesh/agent/sac/app.py +22 -0
  17. solace_agent_mesh/agent/sac/component.py +76 -40
  18. solace_agent_mesh/agent/sac/sac_llm.txt +1 -1
  19. solace_agent_mesh/agent/sac/task_execution_context.py +21 -0
  20. solace_agent_mesh/agent/testing/testing_llm.txt +2 -1
  21. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +13 -148
  22. solace_agent_mesh/agent/tools/dynamic_tool.py +2 -0
  23. solace_agent_mesh/agent/tools/tools_llm.txt +93 -80
  24. solace_agent_mesh/agent/tools/tools_llm_detail.txt +3 -2
  25. solace_agent_mesh/agent/utils/artifact_helpers.py +4 -0
  26. solace_agent_mesh/agent/utils/utils_llm.txt +16 -2
  27. solace_agent_mesh/assets/docs/404.html +3 -3
  28. solace_agent_mesh/assets/docs/assets/js/05749d90.c70b2be9.js +1 -0
  29. solace_agent_mesh/assets/docs/assets/js/15ba94aa.92fea363.js +1 -0
  30. solace_agent_mesh/assets/docs/assets/js/15e40e79.36003774.js +1 -0
  31. solace_agent_mesh/assets/docs/assets/js/2987107d.a80604f9.js +1 -0
  32. solace_agent_mesh/assets/docs/assets/js/3ac1795d.e4870a49.js +1 -0
  33. solace_agent_mesh/assets/docs/assets/js/3ff0015d.b63ee53a.js +1 -0
  34. solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +1 -0
  35. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.45b32c2b.js +1 -0
  36. solace_agent_mesh/assets/docs/assets/js/631738c7.fa471607.js +1 -0
  37. solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +1 -0
  38. solace_agent_mesh/assets/docs/assets/js/6a520c9d.b6e3f2ce.js +1 -0
  39. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.a5b36a60.js +1 -0
  40. solace_agent_mesh/assets/docs/assets/js/71da7b71.374b9d54.js +1 -0
  41. solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.js +1 -0
  42. solace_agent_mesh/assets/docs/assets/js/8b032486.91a91afc.js +1 -0
  43. solace_agent_mesh/assets/docs/assets/js/94e8668d.09ed9234.js +1 -0
  44. solace_agent_mesh/assets/docs/assets/js/{ab9708a8.3e6dd091.js → ab9708a8.245ae0ef.js} +1 -1
  45. solace_agent_mesh/assets/docs/assets/js/ad87452a.9d73dad6.js +1 -0
  46. solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.f902fad8.js +1 -0
  47. solace_agent_mesh/assets/docs/assets/js/da0b5bad.b62f7b08.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/dd817ffc.c37a755e.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.b682e9c2.js +1 -0
  51. solace_agent_mesh/assets/docs/assets/js/de915948.44a432bc.js +1 -0
  52. solace_agent_mesh/assets/docs/assets/js/e04b235d.c9c50c7b.js +1 -0
  53. solace_agent_mesh/assets/docs/assets/js/e3d9abda.d11c67a7.js +1 -0
  54. solace_agent_mesh/assets/docs/assets/js/{e6f9706b.e74a984d.js → e6f9706b.045d0fa1.js} +1 -1
  55. solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +1 -0
  56. solace_agent_mesh/assets/docs/assets/js/f284c35a.5099c51e.js +1 -0
  57. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.74710fc1.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/main.e6488e8b.js +2 -0
  59. solace_agent_mesh/assets/docs/assets/js/runtime~main.d9606d6a.js +1 -0
  60. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +4 -4
  61. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +4 -4
  62. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +4 -4
  63. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +4 -4
  64. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +18 -4
  65. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +4 -4
  66. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +4 -4
  67. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +5 -5
  68. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +4 -4
  69. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +4 -4
  70. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +4 -4
  71. solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +196 -0
  72. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +4 -4
  73. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +5 -5
  74. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +6 -7
  75. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +4 -4
  76. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes-deployment/index.html +47 -0
  77. solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +4 -4
  78. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +4 -4
  79. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +4 -4
  80. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +160 -169
  81. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +4 -4
  82. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +4 -4
  83. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +4 -4
  84. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +4 -4
  85. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +4 -4
  86. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +4 -4
  87. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +5 -5
  88. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +4 -4
  89. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +4 -4
  90. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +4 -4
  91. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +4 -4
  92. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +4 -4
  93. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +4 -4
  94. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +4 -4
  95. solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +59 -0
  96. solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +62 -0
  97. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +10 -6
  98. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +4 -4
  99. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +4 -4
  100. solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +440 -0
  101. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +27 -4
  102. solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +62 -0
  103. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +4 -4
  104. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +5 -4
  105. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +3 -3
  106. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +3 -3
  107. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +290 -0
  108. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +9 -9
  109. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +4 -4
  110. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +4 -4
  111. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +4 -4
  112. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +4 -4
  113. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +251 -0
  114. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +88 -0
  115. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +3 -3
  116. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +3 -3
  117. solace_agent_mesh/assets/docs/lunr-index-1762189824009.json +1 -0
  118. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  119. solace_agent_mesh/assets/docs/search-doc-1762189824009.json +1 -0
  120. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  121. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  122. solace_agent_mesh/cli/__init__.py +1 -1
  123. solace_agent_mesh/cli/commands/docs_cmd.py +4 -1
  124. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +1 -1
  125. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-D4_RMYRh.js → authCallback-tcIFZLis.js} +1 -1
  126. solace_agent_mesh/client/webui/frontend/static/assets/{client-UZ3qU6Bq.js → client-CRYdKo2Q.js} +3 -3
  127. solace_agent_mesh/client/webui/frontend/static/assets/main-CojeY_1w.css +1 -0
  128. solace_agent_mesh/client/webui/frontend/static/assets/main-ILja9MCG.js +353 -0
  129. solace_agent_mesh/client/webui/frontend/static/assets/vendor-CINwxvwV.js +470 -0
  130. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  131. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  132. solace_agent_mesh/common/a2a/a2a_llm.txt +13 -20
  133. solace_agent_mesh/common/a2a/protocol.py +5 -0
  134. solace_agent_mesh/common/a2a/types.py +1 -0
  135. solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +49 -11
  136. solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +23 -6
  137. solace_agent_mesh/common/a2a_spec/schemas/feedback_event.json +51 -0
  138. solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +26 -9
  139. solace_agent_mesh/common/common_llm.txt +13 -34
  140. solace_agent_mesh/common/data_parts.py +20 -4
  141. solace_agent_mesh/common/middleware/middleware_llm.txt +1 -1
  142. solace_agent_mesh/common/sac/sac_llm.txt +1 -1
  143. solace_agent_mesh/common/sam_events/sam_events_llm.txt +1 -1
  144. solace_agent_mesh/common/services/employee_service.py +1 -1
  145. solace_agent_mesh/common/services/providers/providers_llm.txt +3 -2
  146. solace_agent_mesh/common/services/services_llm.txt +9 -4
  147. solace_agent_mesh/common/utils/embeds/constants.py +1 -0
  148. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +1 -1
  149. solace_agent_mesh/common/utils/embeds/modifiers.py +2 -1
  150. solace_agent_mesh/common/utils/embeds/resolver.py +58 -6
  151. solace_agent_mesh/common/utils/embeds/types.py +8 -0
  152. solace_agent_mesh/common/utils/utils_llm.txt +5 -6
  153. solace_agent_mesh/core_a2a/core_a2a_llm.txt +1 -1
  154. solace_agent_mesh/gateway/adapter/__init__.py +1 -0
  155. solace_agent_mesh/gateway/adapter/base.py +143 -0
  156. solace_agent_mesh/gateway/adapter/types.py +221 -0
  157. solace_agent_mesh/gateway/base/app.py +29 -2
  158. solace_agent_mesh/gateway/base/base_llm.txt +10 -8
  159. solace_agent_mesh/gateway/base/component.py +573 -142
  160. solace_agent_mesh/gateway/gateway_llm.txt +55 -59
  161. solace_agent_mesh/gateway/generic/__init__.py +1 -0
  162. solace_agent_mesh/gateway/generic/app.py +50 -0
  163. solace_agent_mesh/gateway/generic/component.py +650 -0
  164. solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +99 -49
  165. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_fulltext_search_indexes.py +92 -0
  166. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_project_users_table.py +72 -0
  167. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +150 -0
  168. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +26 -0
  169. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_projects_table.py +135 -0
  170. solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +26 -20
  171. solace_agent_mesh/gateway/http_sse/app.py +0 -14
  172. solace_agent_mesh/gateway/http_sse/component.py +17 -56
  173. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +1 -1
  174. solace_agent_mesh/gateway/http_sse/dependencies.py +21 -3
  175. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +8 -8
  176. solace_agent_mesh/gateway/http_sse/main.py +23 -5
  177. solace_agent_mesh/gateway/http_sse/repository/__init__.py +19 -1
  178. solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +56 -98
  179. solace_agent_mesh/gateway/http_sse/repository/entities/project.py +81 -0
  180. solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +47 -0
  181. solace_agent_mesh/gateway/http_sse/repository/entities/session.py +23 -1
  182. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +47 -0
  183. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +112 -4
  184. solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +9 -1
  185. solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +51 -60
  186. solace_agent_mesh/gateway/http_sse/repository/models/project_model.py +51 -0
  187. solace_agent_mesh/gateway/http_sse/repository/models/project_user_model.py +75 -0
  188. solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +7 -1
  189. solace_agent_mesh/gateway/http_sse/repository/project_repository.py +172 -0
  190. solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +186 -0
  191. solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +125 -157
  192. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +269 -8
  193. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +143 -51
  194. solace_agent_mesh/gateway/http_sse/routers/config.py +69 -0
  195. solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +198 -94
  196. solace_agent_mesh/gateway/http_sse/routers/dto/requests/project_requests.py +48 -0
  197. solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +68 -18
  198. solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +13 -0
  199. solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +30 -0
  200. solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +51 -35
  201. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +2 -0
  202. solace_agent_mesh/gateway/http_sse/routers/feedback.py +133 -2
  203. solace_agent_mesh/gateway/http_sse/routers/projects.py +542 -0
  204. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +9 -11
  205. solace_agent_mesh/gateway/http_sse/routers/sessions.py +154 -3
  206. solace_agent_mesh/gateway/http_sse/routers/tasks.py +296 -4
  207. solace_agent_mesh/gateway/http_sse/services/project_service.py +403 -0
  208. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +16 -10
  209. solace_agent_mesh/gateway/http_sse/services/session_service.py +178 -6
  210. solace_agent_mesh/gateway/http_sse/shared/exception_handlers.py +2 -3
  211. solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +48 -14
  212. solace_agent_mesh/solace_agent_mesh_llm.txt +1 -1
  213. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.0.dist-info}/METADATA +3 -5
  214. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.0.dist-info}/RECORD +218 -175
  215. solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +0 -1
  216. solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +0 -1
  217. solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +0 -1
  218. solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +0 -1
  219. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +0 -1
  220. solace_agent_mesh/assets/docs/assets/js/631738c7.7c4594c9.js +0 -1
  221. solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +0 -1
  222. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +0 -1
  223. solace_agent_mesh/assets/docs/assets/js/71da7b71.ddbdfbe2.js +0 -1
  224. solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +0 -1
  225. solace_agent_mesh/assets/docs/assets/js/94e8668d.3b883666.js +0 -1
  226. solace_agent_mesh/assets/docs/assets/js/da0b5bad.d08a9466.js +0 -1
  227. solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +0 -1
  228. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +0 -1
  229. solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +0 -1
  230. solace_agent_mesh/assets/docs/assets/js/e3d9abda.6b9493d0.js +0 -1
  231. solace_agent_mesh/assets/docs/assets/js/e92d0134.4f395c6b.js +0 -1
  232. solace_agent_mesh/assets/docs/assets/js/f284c35a.720d2ef2.js +0 -1
  233. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +0 -1
  234. solace_agent_mesh/assets/docs/assets/js/main.ed05b14d.js +0 -2
  235. solace_agent_mesh/assets/docs/assets/js/runtime~main.a8a75e0b.js +0 -1
  236. solace_agent_mesh/assets/docs/lunr-index-1761744323675.json +0 -1
  237. solace_agent_mesh/assets/docs/search-doc-1761744323675.json +0 -1
  238. solace_agent_mesh/client/webui/frontend/static/assets/main--3yJYl7S.css +0 -1
  239. solace_agent_mesh/client/webui/frontend/static/assets/main-DojKHS49.js +0 -342
  240. solace_agent_mesh/client/webui/frontend/static/assets/vendor-DSqhjwq_.js +0 -405
  241. /solace_agent_mesh/assets/docs/assets/js/{main.ed05b14d.js.LICENSE.txt → main.e6488e8b.js.LICENSE.txt} +0 -0
  242. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.0.dist-info}/WHEEL +0 -0
  243. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.0.dist-info}/entry_points.txt +0 -0
  244. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -4,7 +4,7 @@ FastAPI router for managing session-specific artifacts via REST endpoints.
4
4
 
5
5
  import logging
6
6
  from collections.abc import Callable
7
- from typing import TYPE_CHECKING, Any
7
+ from typing import TYPE_CHECKING, Any, Optional
8
8
 
9
9
  from fastapi import (
10
10
  APIRouter,
@@ -13,6 +13,7 @@ from fastapi import (
13
13
  Form,
14
14
  HTTPException,
15
15
  Path,
16
+ Query,
16
17
  UploadFile,
17
18
  status,
18
19
  Request as FastAPIRequest,
@@ -39,8 +40,10 @@ from ....common.utils.embeds import (
39
40
  evaluate_embed,
40
41
  resolve_embeds_recursively_in_string,
41
42
  )
43
+ from ....common.utils.embeds.types import ResolutionMode
42
44
  from ....common.utils.mime_helpers import is_text_based_mime_type
43
45
  from ..dependencies import (
46
+ get_project_service_optional,
44
47
  ValidatedUserConfig,
45
48
  get_sac_component,
46
49
  get_session_validator,
@@ -50,6 +53,7 @@ from ..dependencies import (
50
53
  get_session_business_service_optional,
51
54
  get_db_optional,
52
55
  )
56
+ from ..services.project_service import ProjectService
53
57
 
54
58
 
55
59
  from ..session_manager import SessionManager
@@ -85,6 +89,80 @@ class ArtifactUploadResponse(BaseModel):
85
89
  router = APIRouter()
86
90
 
87
91
 
92
+ def _resolve_storage_context(
93
+ session_id: str,
94
+ project_id: str | None,
95
+ user_id: str,
96
+ validate_session: Callable[[str, str], bool],
97
+ project_service: ProjectService | None,
98
+ log_prefix: str
99
+ ) -> tuple[str, str, str]:
100
+ """
101
+ Resolve storage context from session or project parameters.
102
+
103
+ Returns:
104
+ tuple: (storage_user_id, storage_session_id, context_type)
105
+
106
+ Raises:
107
+ HTTPException: If no valid context found
108
+ """
109
+ # Priority 1: Session context
110
+ if session_id and session_id.strip() and session_id not in ["null", "undefined"]:
111
+ if not validate_session(session_id, user_id):
112
+ log.warning("%s Session validation failed", log_prefix)
113
+ raise HTTPException(
114
+ status_code=status.HTTP_404_NOT_FOUND,
115
+ detail="Session not found or access denied.",
116
+ )
117
+ return user_id, session_id, "session"
118
+
119
+ # Priority 2: Project context (only if persistence is enabled)
120
+ elif project_id and project_id.strip() and project_id not in ["null", "undefined"]:
121
+ if project_service is None:
122
+ log.warning("%s Project context requested but persistence not enabled", log_prefix)
123
+ raise HTTPException(
124
+ status_code=status.HTTP_501_NOT_IMPLEMENTED,
125
+ detail="Project context requires database configuration.",
126
+ )
127
+
128
+ from ....gateway.http_sse.dependencies import SessionLocal
129
+
130
+ if SessionLocal is None:
131
+ log.warning("%s Project context requested but database not configured", log_prefix)
132
+ raise HTTPException(
133
+ status_code=status.HTTP_501_NOT_IMPLEMENTED,
134
+ detail="Project context requires database configuration.",
135
+ )
136
+
137
+ db = SessionLocal()
138
+ try:
139
+ project = project_service.get_project(db, project_id, user_id)
140
+ if not project:
141
+ log.warning("%s Project not found or access denied", log_prefix)
142
+ raise HTTPException(
143
+ status_code=status.HTTP_404_NOT_FOUND,
144
+ detail="Project not found or access denied.",
145
+ )
146
+ return project.user_id, f"project-{project_id}", "project"
147
+ except HTTPException:
148
+ raise
149
+ except Exception as e:
150
+ log.error("%s Error resolving project context: %s", log_prefix, e)
151
+ raise HTTPException(
152
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
153
+ detail="Failed to resolve project context"
154
+ )
155
+ finally:
156
+ db.close()
157
+
158
+ # No valid context
159
+ log.warning("%s No valid context found", log_prefix)
160
+ raise HTTPException(
161
+ status_code=status.HTTP_404_NOT_FOUND,
162
+ detail="No valid context provided.",
163
+ )
164
+
165
+
88
166
  @router.post(
89
167
  "/upload",
90
168
  status_code=status.HTTP_201_CREATED,
@@ -310,33 +388,32 @@ async def upload_artifact_with_session(
310
388
  )
311
389
  async def list_artifact_versions(
312
390
  session_id: str = Path(
313
- ..., title="Session ID", description="The session ID to get artifacts from"
391
+ ..., title="Session ID", description="The session ID to get artifacts from (or 'null' for project context)"
314
392
  ),
315
393
  filename: str = Path(..., title="Filename", description="The name of the artifact"),
394
+ project_id: Optional[str] = Query(None, description="Project ID for project context"),
316
395
  artifact_service: BaseArtifactService = Depends(get_shared_artifact_service),
317
396
  user_id: str = Depends(get_user_id),
318
397
  validate_session: Callable[[str, str], bool] = Depends(get_session_validator),
319
398
  component: "WebUIBackendComponent" = Depends(get_sac_component),
399
+ project_service: ProjectService | None = Depends(get_project_service_optional),
320
400
  user_config: dict = Depends(ValidatedUserConfig(["tool:artifact:list"])),
321
401
  ):
322
402
  """
323
403
  Lists the available integer versions for a given artifact filename
324
- associated with the current user and session ID.
404
+ associated with the specified context (session or project).
325
405
  """
326
406
 
327
407
  log_prefix = f"[ArtifactRouter:ListVersions:{filename}] User={user_id}, Session={session_id} -"
328
408
  log.info("%s Request received.", log_prefix)
329
409
 
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
- )
410
+ # Resolve storage context
411
+ storage_user_id, storage_session_id, context_type = _resolve_storage_context(
412
+ session_id, project_id, user_id, validate_session, project_service, log_prefix
413
+ )
337
414
 
338
415
  if artifact_service is None:
339
- log.error("%s Artifact service is not configured or available.", log_prefix)
416
+ log.error("%s Artifact service not available.", log_prefix)
340
417
  raise HTTPException(
341
418
  status_code=status.HTTP_501_NOT_IMPLEMENTED,
342
419
  detail="Artifact service is not configured.",
@@ -356,10 +433,13 @@ async def list_artifact_versions(
356
433
  try:
357
434
  app_name = component.get_config("name", "A2A_WebUI_App")
358
435
 
436
+ log.info("%s Using %s context: storage_user_id=%s, storage_session_id=%s",
437
+ log_prefix, context_type, storage_user_id, storage_session_id)
438
+
359
439
  versions = await artifact_service.list_versions(
360
440
  app_name=app_name,
361
- user_id=user_id,
362
- session_id=session_id,
441
+ user_id=storage_user_id,
442
+ session_id=storage_session_id,
363
443
  filename=filename,
364
444
  )
365
445
  log.info("%s Found versions: %s", log_prefix, versions)
@@ -368,7 +448,7 @@ async def list_artifact_versions(
368
448
  log.warning("%s Artifact not found.", log_prefix)
369
449
  raise HTTPException(
370
450
  status_code=status.HTTP_404_NOT_FOUND,
371
- detail=f"Artifact '{filename}' not found for this session.",
451
+ detail=f"Artifact '{filename}' not found.",
372
452
  )
373
453
  except Exception as e:
374
454
  log.exception("%s Error listing artifact versions: %s", log_prefix, e)
@@ -392,35 +472,33 @@ async def list_artifact_versions(
392
472
  )
393
473
  async def list_artifacts(
394
474
  session_id: str = Path(
395
- ..., title="Session ID", description="The session ID to list artifacts for"
475
+ ..., title="Session ID", description="The session ID to list artifacts for (or 'null' for project context)"
396
476
  ),
477
+ project_id: Optional[str] = Query(None, description="Project ID for project context"),
397
478
  artifact_service: BaseArtifactService = Depends(get_shared_artifact_service),
398
479
  user_id: str = Depends(get_user_id),
399
480
  validate_session: Callable[[str, str], bool] = Depends(get_session_validator),
400
481
  component: "WebUIBackendComponent" = Depends(get_sac_component),
482
+ project_service: ProjectService | None = Depends(get_project_service_optional),
401
483
  user_config: dict = Depends(ValidatedUserConfig(["tool:artifact:list"])),
402
484
  ):
403
485
  """
404
486
  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.
487
+ for all artifacts associated with the specified context (session or project).
407
488
  """
408
489
 
409
490
  log_prefix = f"[ArtifactRouter:ListInfo] User={user_id}, Session={session_id} -"
410
491
  log.info("%s Request received.", log_prefix)
411
492
 
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.",
493
+ # Resolve storage context (projects vs sessions). This allows for project artiacts
494
+ # to be listed before a session is created.
495
+ try:
496
+ storage_user_id, storage_session_id, context_type = _resolve_storage_context(
497
+ session_id, project_id, user_id, validate_session, project_service, log_prefix
423
498
  )
499
+ except HTTPException:
500
+ log.info("%s No valid context found, returning empty list", log_prefix)
501
+ return []
424
502
 
425
503
  if artifact_service is None:
426
504
  log.error("%s Artifact service is not configured or available.", log_prefix)
@@ -432,22 +510,21 @@ async def list_artifacts(
432
510
  try:
433
511
  app_name = component.get_config("name", "A2A_WebUI_App")
434
512
 
513
+ log.info("%s Using %s context: storage_user_id=%s, storage_session_id=%s",
514
+ log_prefix, context_type, storage_user_id, storage_session_id)
515
+
435
516
  artifact_info_list = await get_artifact_info_list(
436
517
  artifact_service=artifact_service,
437
518
  app_name=app_name,
438
- user_id=user_id,
439
- session_id=session_id,
519
+ user_id=storage_user_id,
520
+ session_id=storage_session_id,
440
521
  )
441
522
 
442
- log.info(
443
- "%s Returning %d artifact details.", log_prefix, len(artifact_info_list)
444
- )
523
+ log.info("%s Returning %d artifact details.", log_prefix, len(artifact_info_list))
445
524
  return artifact_info_list
446
525
 
447
526
  except Exception as e:
448
- log.exception(
449
- "%s Error retrieving artifact details via helper: %s", log_prefix, e
450
- )
527
+ log.exception("%s Error retrieving artifact details: %s", log_prefix, e)
451
528
  raise HTTPException(
452
529
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
453
530
  detail=f"Failed to retrieve artifact details: {str(e)}",
@@ -461,24 +538,31 @@ async def list_artifacts(
461
538
  )
462
539
  async def get_latest_artifact(
463
540
  session_id: str = Path(
464
- ..., title="Session ID", description="The session ID to get artifacts from"
541
+ ..., title="Session ID", description="The session ID to get artifacts from (or 'null' for project context)"
465
542
  ),
466
543
  filename: str = Path(..., title="Filename", description="The name of the artifact"),
544
+ project_id: Optional[str] = Query(None, description="Project ID for project context"),
467
545
  artifact_service: BaseArtifactService = Depends(get_shared_artifact_service),
468
546
  user_id: str = Depends(get_user_id),
469
547
  validate_session: Callable[[str, str], bool] = Depends(get_session_validator),
470
548
  component: "WebUIBackendComponent" = Depends(get_sac_component),
549
+ project_service: ProjectService | None = Depends(get_project_service_optional),
471
550
  user_config: dict = Depends(ValidatedUserConfig(["tool:artifact:load"])),
472
551
  ):
473
552
  """
474
553
  Retrieves the content of the latest version of the specified artifact
475
- associated with the current user and session ID.
554
+ associated with the specified context (session or project).
476
555
  """
477
556
  log_prefix = (
478
557
  f"[ArtifactRouter:GetLatest:{filename}] User={user_id}, Session={session_id} -"
479
558
  )
480
559
  log.info("%s Request received.", log_prefix)
481
560
 
561
+ # Resolve storage context
562
+ storage_user_id, storage_session_id, context_type = _resolve_storage_context(
563
+ session_id, project_id, user_id, validate_session, project_service, log_prefix
564
+ )
565
+
482
566
  if artifact_service is None:
483
567
  log.error("%s Artifact service is not configured or available.", log_prefix)
484
568
  raise HTTPException(
@@ -488,10 +572,14 @@ async def get_latest_artifact(
488
572
 
489
573
  try:
490
574
  app_name = component.get_config("name", "A2A_WebUI_App")
575
+
576
+ log.info("%s Using %s context: storage_user_id=%s, storage_session_id=%s",
577
+ log_prefix, context_type, storage_user_id, storage_session_id)
578
+
491
579
  artifact_part = await artifact_service.load_artifact(
492
580
  app_name=app_name,
493
- user_id=user_id,
494
- session_id=session_id,
581
+ user_id=storage_user_id,
582
+ session_id=storage_session_id,
495
583
  filename=filename,
496
584
  )
497
585
 
@@ -537,6 +625,7 @@ async def get_latest_artifact(
537
625
  context=context_for_resolver,
538
626
  resolver_func=evaluate_embed,
539
627
  types_to_resolve=LATE_EMBED_TYPES,
628
+ resolution_mode=ResolutionMode.RECURSIVE_ARTIFACT_CONTENT,
540
629
  log_identifier=f"{log_prefix}[RecursiveResolve]",
541
630
  config=config_for_resolver,
542
631
  max_depth=component.gateway_recursive_embed_depth,
@@ -596,7 +685,7 @@ async def get_latest_artifact(
596
685
  )
597
686
  async def get_specific_artifact_version(
598
687
  session_id: str = Path(
599
- ..., title="Session ID", description="The session ID to get artifacts from"
688
+ ..., title="Session ID", description="The session ID to get artifacts from (or 'null' for project context)"
600
689
  ),
601
690
  filename: str = Path(..., title="Filename", description="The name of the artifact"),
602
691
  version: int | str = Path(
@@ -604,26 +693,25 @@ async def get_specific_artifact_version(
604
693
  title="Version",
605
694
  description="The specific version number to retrieve, or 'latest'",
606
695
  ),
696
+ project_id: Optional[str] = Query(None, description="Project ID for project context"),
607
697
  artifact_service: BaseArtifactService = Depends(get_shared_artifact_service),
608
698
  user_id: str = Depends(get_user_id),
609
699
  validate_session: Callable[[str, str], bool] = Depends(get_session_validator),
610
700
  component: "WebUIBackendComponent" = Depends(get_sac_component),
701
+ project_service: ProjectService | None = Depends(get_project_service_optional),
611
702
  user_config: dict = Depends(ValidatedUserConfig(["tool:artifact:load"])),
612
703
  ):
613
704
  """
614
705
  Retrieves the content of a specific version of the specified artifact
615
- associated with the current user and session ID.
706
+ associated with the specified context (session or project).
616
707
  """
617
708
  log_prefix = f"[ArtifactRouter:GetVersion:{filename} v{version}] User={user_id}, Session={session_id} -"
618
709
  log.info("%s Request received.", log_prefix)
619
710
 
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
- )
711
+ # Resolve storage context
712
+ storage_user_id, storage_session_id, context_type = _resolve_storage_context(
713
+ session_id, project_id, user_id, validate_session, project_service, log_prefix
714
+ )
627
715
 
628
716
  if artifact_service is None:
629
717
  log.error("%s Artifact service is not configured or available.", log_prefix)
@@ -635,11 +723,14 @@ async def get_specific_artifact_version(
635
723
  try:
636
724
  app_name = component.get_config("name", "A2A_WebUI_App")
637
725
 
726
+ log.info("%s Using %s context: storage_user_id=%s, storage_session_id=%s",
727
+ log_prefix, context_type, storage_user_id, storage_session_id)
728
+
638
729
  load_result = await load_artifact_content_or_metadata(
639
730
  artifact_service=artifact_service,
640
731
  app_name=app_name,
641
- user_id=user_id,
642
- session_id=session_id,
732
+ user_id=storage_user_id,
733
+ session_id=storage_session_id,
643
734
  filename=filename,
644
735
  version=version,
645
736
  load_metadata_only=False,
@@ -715,6 +806,7 @@ async def get_specific_artifact_version(
715
806
  context=context_for_resolver,
716
807
  resolver_func=evaluate_embed,
717
808
  types_to_resolve=LATE_EMBED_TYPES,
809
+ resolution_mode=ResolutionMode.RECURSIVE_ARTIFACT_CONTENT,
718
810
  log_identifier=f"{log_prefix}[RecursiveResolve]",
719
811
  config=config_for_resolver,
720
812
  max_depth=component.gateway_recursive_embed_depth,
@@ -7,6 +7,7 @@ from fastapi import APIRouter, Depends, HTTPException, status
7
7
  from typing import Dict, Any
8
8
 
9
9
  from ....gateway.http_sse.dependencies import get_sac_component, get_api_config
10
+ from ..routers.dto.requests.project_requests import CreateProjectRequest, UpdateProjectRequest
10
11
  from typing import TYPE_CHECKING
11
12
 
12
13
  if TYPE_CHECKING:
@@ -17,6 +18,64 @@ log = logging.getLogger(__name__)
17
18
  router = APIRouter()
18
19
 
19
20
 
21
+ def _get_validation_limits() -> Dict[str, Any]:
22
+ """
23
+ Extract validation limits from Pydantic models to expose to frontend.
24
+ This ensures frontend and backend validation limits stay in sync.
25
+ """
26
+ # Extract limits from CreateProjectRequest model
27
+ create_fields = CreateProjectRequest.model_fields
28
+
29
+ return {
30
+ "projectNameMax": create_fields["name"].metadata[1].max_length if create_fields["name"].metadata else 255,
31
+ "projectDescriptionMax": create_fields["description"].metadata[0].max_length if create_fields["description"].metadata else 1000,
32
+ "projectInstructionsMax": create_fields["system_prompt"].metadata[0].max_length if create_fields["system_prompt"].metadata else 4000,
33
+ }
34
+
35
+
36
+ def _determine_projects_enabled(
37
+ component: "WebUIBackendComponent",
38
+ api_config: Dict[str, Any],
39
+ log_prefix: str
40
+ ) -> bool:
41
+ """
42
+ Determines if projects feature should be enabled.
43
+
44
+ Logic:
45
+ 1. Check if persistence is enabled (required for projects)
46
+ 2. Check explicit projects.enabled config
47
+ 3. Check frontend_feature_enablement.projects override
48
+
49
+ Returns:
50
+ bool: True if projects should be enabled
51
+ """
52
+ # Projects require persistence
53
+ persistence_enabled = api_config.get("persistence_enabled", False)
54
+ if not persistence_enabled:
55
+ log.debug("%s Projects disabled: persistence is not enabled", log_prefix)
56
+ return False
57
+
58
+ # Check explicit projects config
59
+ projects_config = component.get_config("projects", {})
60
+ if isinstance(projects_config, dict):
61
+ projects_explicitly_enabled = projects_config.get("enabled", True)
62
+ if not projects_explicitly_enabled:
63
+ log.debug("%s Projects disabled: explicitly disabled in config", log_prefix)
64
+ return False
65
+
66
+ # Check frontend_feature_enablement override
67
+ feature_flags = component.get_config("frontend_feature_enablement", {})
68
+ if "projects" in feature_flags:
69
+ projects_flag = feature_flags.get("projects", True)
70
+ if not projects_flag:
71
+ log.debug("%s Projects disabled: disabled in frontend_feature_enablement", log_prefix)
72
+ return False
73
+
74
+ # All checks passed
75
+ log.debug("%s Projects enabled: persistence enabled and no explicit disable", log_prefix)
76
+ return True
77
+
78
+
20
79
  @router.get("/config", response_model=Dict[str, Any])
21
80
  async def get_app_config(
22
81
  component: "WebUIBackendComponent" = Depends(get_sac_component),
@@ -51,6 +110,15 @@ async def get_app_config(
51
110
  session_type
52
111
  )
53
112
  feedback_enabled = False
113
+
114
+ # Determine if projects should be enabled
115
+ # Projects require SQL session storage for persistence
116
+ projects_enabled = _determine_projects_enabled(component, api_config, log_prefix)
117
+ feature_enablement["projects"] = projects_enabled
118
+ if projects_enabled:
119
+ log.debug("%s Projects feature flag is enabled.", log_prefix)
120
+ else:
121
+ log.debug("%s Projects feature flag is disabled.", log_prefix)
54
122
 
55
123
  config_data = {
56
124
  "frontend_server_url": "",
@@ -68,6 +136,7 @@ async def get_app_config(
68
136
  "frontend_bot_name": component.get_config("frontend_bot_name", "A2A Agent"),
69
137
  "frontend_feature_enablement": feature_enablement,
70
138
  "persistence_enabled": api_config.get("persistence_enabled", False),
139
+ "validation_limits": _get_validation_limits(),
71
140
  }
72
141
  log.debug("%sReturning frontend configuration.", log_prefix)
73
142
  return config_data