solace-agent-mesh 1.6.3__py3-none-any.whl → 1.7.1__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.f213fe0c.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-1762283454666.json +1 -0
  118. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  119. solace_agent_mesh/assets/docs/search-doc-1762283454666.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.1.dist-info}/METADATA +3 -5
  214. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.1.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.f213fe0c.js.LICENSE.txt} +0 -0
  242. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.1.dist-info}/WHEEL +0 -0
  243. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.1.dist-info}/entry_points.txt +0 -0
  244. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.1.dist-info}/licenses/LICENSE +0 -0
@@ -2,14 +2,17 @@
2
2
  Session repository implementation using SQLAlchemy.
3
3
  """
4
4
 
5
- from sqlalchemy.orm import Session as DBSession
5
+ from sqlalchemy import or_, func
6
+ from sqlalchemy.orm import Session as DBSession, joinedload
6
7
 
7
8
  from ..shared.base_repository import PaginatedRepository
8
9
  from ..shared.pagination import PaginationParams
9
10
  from ..shared.types import SessionId, UserId
11
+ from ..shared import now_epoch_ms
10
12
  from .entities import Session
11
13
  from .interfaces import ISessionRepository
12
14
  from .models import CreateSessionModel, SessionModel, UpdateSessionModel
15
+ from .models.chat_task_model import ChatTaskModel
13
16
 
14
17
 
15
18
  class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepository):
@@ -24,10 +27,20 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
24
27
  return "session"
25
28
 
26
29
  def find_by_user(
27
- self, session: DBSession, user_id: UserId, pagination: PaginationParams | None = None
30
+ self, session: DBSession, user_id: UserId, pagination: PaginationParams | None = None, project_id: str | None = None
28
31
  ) -> list[Session]:
29
- """Find all sessions for a specific user."""
30
- query = session.query(SessionModel).filter(SessionModel.user_id == user_id)
32
+ """Find all sessions for a specific user with optional project filtering."""
33
+ query = session.query(SessionModel).filter(
34
+ SessionModel.user_id == user_id,
35
+ SessionModel.deleted_at.is_(None) # Exclude soft-deleted sessions
36
+ )
37
+
38
+ # Optional project filtering for project-specific views
39
+ if project_id is not None:
40
+ query = query.filter(SessionModel.project_id == project_id)
41
+
42
+ # Eager load project relationship
43
+ query = query.options(joinedload(SessionModel.project))
31
44
  query = query.order_by(SessionModel.updated_time.desc())
32
45
 
33
46
  if pagination:
@@ -36,12 +49,19 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
36
49
  models = query.all()
37
50
  return [Session.model_validate(model) for model in models]
38
51
 
39
- def count_by_user(self, session: DBSession, user_id: UserId) -> int:
40
- """Count total sessions for a specific user."""
41
- return (
42
- session.query(SessionModel).filter(SessionModel.user_id == user_id).count()
52
+ def count_by_user(self, session: DBSession, user_id: UserId, project_id: str | None = None) -> int:
53
+ """Count total sessions for a specific user with optional project filtering."""
54
+ query = session.query(SessionModel).filter(
55
+ SessionModel.user_id == user_id,
56
+ SessionModel.deleted_at.is_(None) # Exclude soft-deleted sessions
43
57
  )
44
58
 
59
+ # Optional project filtering for project-specific views
60
+ if project_id is not None:
61
+ query = query.filter(SessionModel.project_id == project_id)
62
+
63
+ return query.count()
64
+
45
65
  def find_user_session(
46
66
  self, session: DBSession, session_id: SessionId, user_id: UserId
47
67
  ) -> Session | None:
@@ -51,6 +71,7 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
51
71
  .filter(
52
72
  SessionModel.id == session_id,
53
73
  SessionModel.user_id == user_id,
74
+ SessionModel.deleted_at.is_(None) # Exclude soft-deleted sessions
54
75
  )
55
76
  .first()
56
77
  )
@@ -66,6 +87,7 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
66
87
  update_model = UpdateSessionModel(
67
88
  name=session.name,
68
89
  agent_id=session.agent_id,
90
+ project_id=session.project_id,
69
91
  updated_time=session.updated_time,
70
92
  )
71
93
  return self.update(
@@ -77,6 +99,7 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
77
99
  name=session.name,
78
100
  user_id=session.user_id,
79
101
  agent_id=session.agent_id,
102
+ project_id=session.project_id,
80
103
  created_time=session.created_time,
81
104
  updated_time=session.updated_time,
82
105
  )
@@ -100,3 +123,241 @@ class SessionRepository(PaginatedRepository[SessionModel, Session], ISessionRepo
100
123
  # Use BaseRepository delete method
101
124
  super().delete(db_session, session_id)
102
125
  return True
126
+
127
+ def soft_delete(self, db_session: DBSession, session_id: SessionId, user_id: UserId) -> bool:
128
+ """Soft delete a session belonging to a user."""
129
+ session_model = (
130
+ db_session.query(SessionModel)
131
+ .filter(
132
+ SessionModel.id == session_id,
133
+ SessionModel.user_id == user_id,
134
+ SessionModel.deleted_at.is_(None)
135
+ )
136
+ .first()
137
+ )
138
+
139
+ if not session_model:
140
+ return False
141
+
142
+ # Perform soft delete
143
+ session_model.deleted_at = now_epoch_ms()
144
+ session_model.deleted_by = user_id
145
+ session_model.updated_time = now_epoch_ms()
146
+
147
+ db_session.flush()
148
+ return True
149
+
150
+ def soft_delete_by_project(self, db_session: DBSession, project_id: str, user_id: UserId) -> int:
151
+ """
152
+ Soft delete all sessions belonging to a specific project.
153
+ Used when cascading project deletion.
154
+
155
+ Args:
156
+ db_session: Database session
157
+ project_id: The project ID
158
+ user_id: The user ID (for deleted_by tracking)
159
+
160
+ Returns:
161
+ int: Number of sessions soft deleted
162
+ """
163
+ now = now_epoch_ms()
164
+
165
+ # Find all non-deleted sessions for this project
166
+ sessions_to_delete = (
167
+ db_session.query(SessionModel)
168
+ .filter(
169
+ SessionModel.project_id == project_id,
170
+ SessionModel.user_id == user_id,
171
+ SessionModel.deleted_at.is_(None)
172
+ )
173
+ .all()
174
+ )
175
+
176
+ # Soft delete each session
177
+ for session_model in sessions_to_delete:
178
+ session_model.deleted_at = now
179
+ session_model.deleted_by = user_id
180
+ session_model.updated_time = now
181
+
182
+ db_session.flush()
183
+ return len(sessions_to_delete)
184
+
185
+ def move_to_project(
186
+ self, db_session: DBSession, session_id: SessionId, user_id: UserId, new_project_id: str | None
187
+ ) -> Session | None:
188
+ """Move a session to a different project."""
189
+ session_model = (
190
+ db_session.query(SessionModel)
191
+ .filter(
192
+ SessionModel.id == session_id,
193
+ SessionModel.user_id == user_id,
194
+ SessionModel.deleted_at.is_(None)
195
+ )
196
+ .first()
197
+ )
198
+
199
+ if not session_model:
200
+ return None
201
+
202
+ # Update project_id
203
+ session_model.project_id = new_project_id
204
+ session_model.updated_time = now_epoch_ms()
205
+
206
+ db_session.flush()
207
+ db_session.refresh(session_model)
208
+
209
+ return Session.model_validate(session_model)
210
+
211
+ def search(
212
+ self,
213
+ db_session: DBSession,
214
+ user_id: UserId,
215
+ query: str,
216
+ pagination: PaginationParams | None = None,
217
+ project_id: str | None = None
218
+ ) -> list[Session]:
219
+ """
220
+ Search sessions by name or content.
221
+
222
+ Uses PostgreSQL full-text search when available (for queries >= 3 chars),
223
+ falls back to ILIKE for SQLite or short queries.
224
+ """
225
+ # Base query - only non-deleted sessions for the user
226
+ base_query = db_session.query(SessionModel).filter(
227
+ SessionModel.user_id == user_id,
228
+ SessionModel.deleted_at.is_(None)
229
+ )
230
+
231
+ # Optional project filtering
232
+ if project_id is not None:
233
+ base_query = base_query.filter(SessionModel.project_id == project_id)
234
+
235
+ # Detect database dialect
236
+ dialect_name = db_session.bind.dialect.name
237
+ use_fts = dialect_name == 'postgresql' and len(query.strip()) >= 3
238
+
239
+ if use_fts:
240
+ # PostgreSQL full-text search for better performance
241
+ matching_chat_tasks = (
242
+ db_session.query(ChatTaskModel.session_id)
243
+ .filter(
244
+ or_(
245
+ func.to_tsvector('english', func.coalesce(ChatTaskModel.user_message, ''))
246
+ .op('@@')(func.plainto_tsquery('english', query)),
247
+ func.to_tsvector('english', ChatTaskModel.message_bubbles)
248
+ .op('@@')(func.plainto_tsquery('english', query))
249
+ )
250
+ )
251
+ .distinct()
252
+ .subquery()
253
+ )
254
+
255
+ search_query = base_query.filter(
256
+ or_(
257
+ func.to_tsvector('english', func.coalesce(SessionModel.name, ''))
258
+ .op('@@')(func.plainto_tsquery('english', query)),
259
+ SessionModel.id.in_(matching_chat_tasks)
260
+ )
261
+ )
262
+ else:
263
+ # ILIKE search for SQLite or short queries
264
+ search_pattern = f"%{query}%"
265
+ matching_chat_tasks = (
266
+ db_session.query(ChatTaskModel.session_id)
267
+ .filter(
268
+ or_(
269
+ ChatTaskModel.user_message.ilike(search_pattern),
270
+ ChatTaskModel.message_bubbles.ilike(search_pattern)
271
+ )
272
+ )
273
+ .distinct()
274
+ .subquery()
275
+ )
276
+
277
+ search_query = base_query.filter(
278
+ or_(
279
+ SessionModel.name.ilike(search_pattern),
280
+ SessionModel.id.in_(matching_chat_tasks)
281
+ )
282
+ )
283
+
284
+ # Eager load project relationship
285
+ search_query = search_query.options(joinedload(SessionModel.project))
286
+ search_query = search_query.order_by(SessionModel.updated_time.desc())
287
+
288
+ if pagination:
289
+ search_query = search_query.offset(pagination.offset).limit(pagination.page_size)
290
+
291
+ models = search_query.all()
292
+ return [Session.model_validate(model) for model in models]
293
+
294
+ def count_search_results(
295
+ self,
296
+ db_session: DBSession,
297
+ user_id: UserId,
298
+ query: str,
299
+ project_id: str | None = None
300
+ ) -> int:
301
+ """
302
+ Count search results for pagination.
303
+
304
+ Uses same database-agnostic logic as search() method for consistency.
305
+ """
306
+ # Base query - only non-deleted sessions for the user
307
+ base_query = db_session.query(SessionModel).filter(
308
+ SessionModel.user_id == user_id,
309
+ SessionModel.deleted_at.is_(None)
310
+ )
311
+
312
+ if project_id is not None:
313
+ base_query = base_query.filter(SessionModel.project_id == project_id)
314
+
315
+ dialect_name = db_session.bind.dialect.name
316
+ use_fts = dialect_name == 'postgresql' and len(query.strip()) >= 3
317
+
318
+ if use_fts:
319
+ # PostgreSQL full-text search
320
+ matching_chat_tasks = (
321
+ db_session.query(ChatTaskModel.session_id)
322
+ .filter(
323
+ or_(
324
+ func.to_tsvector('english', func.coalesce(ChatTaskModel.user_message, ''))
325
+ .op('@@')(func.plainto_tsquery('english', query)),
326
+ func.to_tsvector('english', ChatTaskModel.message_bubbles)
327
+ .op('@@')(func.plainto_tsquery('english', query))
328
+ )
329
+ )
330
+ .distinct()
331
+ .subquery()
332
+ )
333
+
334
+ search_query = base_query.filter(
335
+ or_(
336
+ func.to_tsvector('english', func.coalesce(SessionModel.name, ''))
337
+ .op('@@')(func.plainto_tsquery('english', query)),
338
+ SessionModel.id.in_(matching_chat_tasks)
339
+ )
340
+ )
341
+ else:
342
+ # ILIKE search for SQLite or short queries
343
+ search_pattern = f"%{query}%"
344
+ matching_chat_tasks = (
345
+ db_session.query(ChatTaskModel.session_id)
346
+ .filter(
347
+ or_(
348
+ ChatTaskModel.user_message.ilike(search_pattern),
349
+ ChatTaskModel.message_bubbles.ilike(search_pattern)
350
+ )
351
+ )
352
+ .distinct()
353
+ .subquery()
354
+ )
355
+
356
+ search_query = base_query.filter(
357
+ or_(
358
+ SessionModel.name.ilike(search_pattern),
359
+ SessionModel.id.in_(matching_chat_tasks)
360
+ )
361
+ )
362
+
363
+ return search_query.count()