solace-agent-mesh 1.4.12__py3-none-any.whl → 1.5.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 (359) hide show
  1. solace_agent_mesh/agent/adk/adk_llm.txt +3 -4
  2. solace_agent_mesh/agent/adk/adk_llm_detail.txt +566 -0
  3. solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +1 -1
  4. solace_agent_mesh/agent/adk/callbacks.py +56 -5
  5. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +3 -1
  6. solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +2 -1
  7. solace_agent_mesh/agent/adk/mcp_content_processor.py +2 -1
  8. solace_agent_mesh/agent/adk/models/lite_llm.py +1 -0
  9. solace_agent_mesh/agent/adk/models/models_llm.txt +1 -2
  10. solace_agent_mesh/agent/adk/runner.py +3 -1
  11. solace_agent_mesh/agent/adk/services.py +4 -1
  12. solace_agent_mesh/agent/adk/setup.py +3 -1
  13. solace_agent_mesh/agent/adk/tool_wrapper.py +2 -2
  14. solace_agent_mesh/agent/agent_llm.txt +1 -1
  15. solace_agent_mesh/agent/agent_llm_detail.txt +1702 -0
  16. solace_agent_mesh/agent/protocol/event_handlers.py +4 -14
  17. solace_agent_mesh/agent/protocol/protocol_llm.txt +15 -2
  18. solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +92 -0
  19. solace_agent_mesh/agent/sac/app.py +3 -1
  20. solace_agent_mesh/agent/sac/component.py +55 -22
  21. solace_agent_mesh/agent/sac/sac_llm.txt +15 -1
  22. solace_agent_mesh/agent/sac/sac_llm_detail.txt +200 -0
  23. solace_agent_mesh/agent/sac/task_execution_context.py +73 -0
  24. solace_agent_mesh/agent/testing/testing_llm_detail.txt +68 -0
  25. solace_agent_mesh/agent/tools/audio_tools.py +2 -1
  26. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +3 -1
  27. solace_agent_mesh/agent/tools/builtin_data_analysis_tools.py +3 -1
  28. solace_agent_mesh/agent/tools/dynamic_tool.py +2 -1
  29. solace_agent_mesh/agent/tools/general_agent_tools.py +2 -1
  30. solace_agent_mesh/agent/tools/image_tools.py +2 -1
  31. solace_agent_mesh/agent/tools/peer_agent_tool.py +2 -1
  32. solace_agent_mesh/agent/tools/registry.py +3 -1
  33. solace_agent_mesh/agent/tools/test_tools.py +2 -1
  34. solace_agent_mesh/agent/tools/tools_llm.txt +148 -154
  35. solace_agent_mesh/agent/tools/tools_llm_detail.txt +274 -0
  36. solace_agent_mesh/agent/tools/web_tools.py +2 -1
  37. solace_agent_mesh/agent/utils/artifact_helpers.py +3 -1
  38. solace_agent_mesh/agent/utils/config_parser.py +3 -1
  39. solace_agent_mesh/agent/utils/utils_llm.txt +1 -1
  40. solace_agent_mesh/agent/utils/utils_llm_detail.txt +149 -0
  41. solace_agent_mesh/assets/docs/404.html +3 -3
  42. solace_agent_mesh/assets/docs/assets/js/{b7006a3a.73a79653.js → 032c2d61.f3d37824.js} +1 -1
  43. solace_agent_mesh/assets/docs/assets/js/0bcf40b7.c019ad46.js +1 -0
  44. solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +1 -0
  45. solace_agent_mesh/assets/docs/assets/js/2131ec11.5c7a1f6e.js +1 -0
  46. solace_agent_mesh/assets/docs/assets/js/{2334.622a6395.js → 2334.1cf50a20.js} +1 -1
  47. solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/341393d4.0fac2613.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/{3624.b524e433.js → 3624.0eaa1fd0.js} +1 -1
  51. solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +1 -0
  52. solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +1 -0
  53. solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +1 -0
  54. solace_agent_mesh/assets/docs/assets/js/509e993c.4c7a1a6d.js +1 -0
  55. solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +1 -0
  56. solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +1 -0
  57. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.e49689dd.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/6063ff4c.ef84f702.js +1 -0
  59. solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +1 -0
  60. solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +1 -0
  61. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.39d5851d.js +1 -0
  62. solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +1 -0
  63. solace_agent_mesh/assets/docs/assets/js/6fdfefc7.99de744e.js +1 -0
  64. solace_agent_mesh/assets/docs/assets/js/71da7b71.804d6567.js +1 -0
  65. solace_agent_mesh/assets/docs/assets/js/722f809d.965da774.js +1 -0
  66. solace_agent_mesh/assets/docs/assets/js/742f027b.46c07808.js +1 -0
  67. solace_agent_mesh/assets/docs/assets/js/77cf947d.64c9bd6c.js +1 -0
  68. solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +1 -0
  69. solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +1 -0
  70. solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +1 -0
  71. solace_agent_mesh/assets/docs/assets/js/{8591.d7c16be6.js → 8591.5d015485.js} +2 -2
  72. solace_agent_mesh/assets/docs/assets/js/{8731.49e930c2.js → 8731.6c1dbf0c.js} +1 -1
  73. solace_agent_mesh/assets/docs/assets/js/945fb41e.6f4cdffd.js +1 -0
  74. solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +1 -0
  75. solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +1 -0
  76. solace_agent_mesh/assets/docs/assets/js/9e9d0a82.dd810042.js +1 -0
  77. solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e6dd091.js +1 -0
  78. solace_agent_mesh/assets/docs/assets/js/ad71b5ed.60668e9e.js +1 -0
  79. solace_agent_mesh/assets/docs/assets/js/c198a0dc.8f31f867.js +1 -0
  80. solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +1 -0
  81. solace_agent_mesh/assets/docs/assets/js/da0b5bad.9d369087.js +1 -0
  82. solace_agent_mesh/assets/docs/assets/js/db924877.cbc66f02.js +1 -0
  83. solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +1 -0
  84. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +1 -0
  85. solace_agent_mesh/assets/docs/assets/js/de5f4c65.e8241890.js +1 -0
  86. solace_agent_mesh/assets/docs/assets/js/de915948.139b4b9c.js +1 -0
  87. solace_agent_mesh/assets/docs/assets/js/e3d9abda.2b916f9e.js +1 -0
  88. solace_agent_mesh/assets/docs/assets/js/e6f9706b.582a78ca.js +1 -0
  89. solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +1 -0
  90. solace_agent_mesh/assets/docs/assets/js/f284c35a.5766a13d.js +1 -0
  91. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.9c0297a6.js +1 -0
  92. solace_agent_mesh/assets/docs/assets/js/main.bd3c34f3.js +2 -0
  93. solace_agent_mesh/assets/docs/assets/js/runtime~main.18dc45dd.js +1 -0
  94. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +143 -0
  95. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/artifact-management/index.html +7 -7
  96. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/audio-tools/index.html +7 -7
  97. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/data-analysis-tools/index.html +8 -8
  98. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/embeds/index.html +6 -6
  99. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/index.html +11 -11
  100. solace_agent_mesh/assets/docs/docs/documentation/{concepts → components}/cli/index.html +25 -25
  101. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +91 -0
  102. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +29 -0
  103. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +55 -0
  104. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +110 -0
  105. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +104 -0
  106. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +57 -0
  107. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +25 -0
  108. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +59 -0
  109. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/create-agents/index.html +113 -152
  110. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/create-gateways/index.html +9 -9
  111. solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/creating-python-tools/index.html +12 -12
  112. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +54 -0
  113. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +32 -0
  114. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +55 -0
  115. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/bedrock-agents/index.html +25 -25
  116. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/custom-agent/index.html +13 -13
  117. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/event-mesh-gateway/index.html +11 -11
  118. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/mcp-integration/index.html +10 -10
  119. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/mongodb-integration/index.html +13 -13
  120. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/rag-integration/index.html +13 -13
  121. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/rest-gateway/index.html +10 -10
  122. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +72 -0
  123. solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/sql-database/index.html +14 -14
  124. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +33 -0
  125. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +83 -0
  126. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +222 -0
  127. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +161 -0
  128. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +75 -0
  129. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +53 -0
  130. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +35 -100
  131. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +41 -0
  132. solace_agent_mesh/assets/docs/docs/documentation/{getting-started → installing-and-configuring}/configurations/index.html +56 -50
  133. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +25 -0
  134. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +76 -0
  135. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +63 -0
  136. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +142 -0
  137. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +100 -0
  138. solace_agent_mesh/assets/docs/docs/documentation/{Migrations/A2A Upgrade To 0.3.0/a2a-technical-migration-map/index.html → migrations/a2a-upgrade/a2a-technical-migration-map/index.html} +10 -11
  139. solace_agent_mesh/assets/docs/img/solace-logo.png +0 -0
  140. solace_agent_mesh/assets/docs/lunr-index-1760121512891.json +1 -0
  141. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  142. solace_agent_mesh/assets/docs/search-doc-1760121512891.json +1 -0
  143. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  144. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  145. solace_agent_mesh/cli/__init__.py +1 -1
  146. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-j1LW-wlq.js → authCallback-DwrxZE0E.js} +1 -1
  147. solace_agent_mesh/client/webui/frontend/static/assets/{client-B9p_nFNA.js → client-DarGQzyw.js} +1 -1
  148. solace_agent_mesh/client/webui/frontend/static/assets/main-2nd1gbaH.js +339 -0
  149. solace_agent_mesh/client/webui/frontend/static/assets/main-DoKXctCM.css +1 -0
  150. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-CS5YMf8a.js → vendor-BKIeiHj_.js} +80 -70
  151. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  152. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  153. solace_agent_mesh/common/a2a/a2a_llm.txt +1 -1
  154. solace_agent_mesh/common/a2a/a2a_llm_detail.txt +193 -0
  155. solace_agent_mesh/common/a2a/artifact.py +2 -1
  156. solace_agent_mesh/common/a2a/protocol.py +3 -2
  157. solace_agent_mesh/common/a2a/translation.py +3 -1
  158. solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +1 -1
  159. solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +736 -0
  160. solace_agent_mesh/common/a2a_spec/schemas/llm_invocation.json +23 -0
  161. solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +93 -15
  162. solace_agent_mesh/common/a2a_spec/schemas/tool_result.json +23 -0
  163. solace_agent_mesh/common/common_llm.txt +24 -39
  164. solace_agent_mesh/common/common_llm_detail.txt +2562 -0
  165. solace_agent_mesh/common/data_parts.py +9 -1
  166. solace_agent_mesh/common/middleware/config_resolver.py +3 -1
  167. solace_agent_mesh/common/middleware/middleware_llm_detail.txt +185 -0
  168. solace_agent_mesh/common/middleware/registry.py +3 -1
  169. solace_agent_mesh/common/sac/sac_llm.txt +1 -1
  170. solace_agent_mesh/common/sac/sac_llm_detail.txt +82 -0
  171. solace_agent_mesh/common/sac/sam_component_base.py +2 -1
  172. solace_agent_mesh/common/sam_events/event_service.py +3 -2
  173. solace_agent_mesh/common/sam_events/sam_events_llm.txt +104 -0
  174. solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +115 -0
  175. solace_agent_mesh/common/services/employee_service.py +3 -1
  176. solace_agent_mesh/common/services/identity_service.py +2 -1
  177. solace_agent_mesh/common/services/providers/local_file_identity_service.py +2 -1
  178. solace_agent_mesh/common/services/services_llm.txt +57 -6
  179. solace_agent_mesh/common/services/services_llm_detail.txt +459 -0
  180. solace_agent_mesh/common/utils/artifact_utils.py +3 -1
  181. solace_agent_mesh/common/utils/asyncio_macos_fix.py +3 -1
  182. solace_agent_mesh/common/utils/embeds/converter.py +3 -1
  183. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +1 -1
  184. solace_agent_mesh/common/utils/embeds/evaluators.py +2 -1
  185. solace_agent_mesh/common/utils/embeds/modifiers.py +3 -2
  186. solace_agent_mesh/common/utils/embeds/resolver.py +2 -1
  187. solace_agent_mesh/common/utils/initializer.py +3 -1
  188. solace_agent_mesh/common/utils/message_utils.py +2 -1
  189. solace_agent_mesh/common/utils/push_notification_auth.py +3 -2
  190. solace_agent_mesh/common/utils/utils_llm.txt +75 -87
  191. solace_agent_mesh/common/utils/utils_llm_detail.txt +572 -0
  192. solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +101 -0
  193. solace_agent_mesh/core_a2a/service.py +2 -2
  194. solace_agent_mesh/gateway/base/app.py +3 -2
  195. solace_agent_mesh/gateway/base/base_llm.txt +1 -1
  196. solace_agent_mesh/gateway/base/base_llm_detail.txt +235 -0
  197. solace_agent_mesh/gateway/base/component.py +3 -1
  198. solace_agent_mesh/gateway/base/task_context.py +2 -1
  199. solace_agent_mesh/gateway/gateway_llm.txt +242 -235
  200. solace_agent_mesh/gateway/gateway_llm_detail.txt +3885 -0
  201. solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +295 -0
  202. solace_agent_mesh/gateway/http_sse/alembic/env.py +10 -1
  203. solace_agent_mesh/gateway/http_sse/alembic/versions/20251006_98882922fa59_add_tasks_events_feedback_chat_tasks.py +190 -0
  204. solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +155 -0
  205. solace_agent_mesh/gateway/http_sse/alembic.ini +1 -1
  206. solace_agent_mesh/gateway/http_sse/app.py +150 -3
  207. solace_agent_mesh/gateway/http_sse/component.py +372 -61
  208. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +46 -6
  209. solace_agent_mesh/gateway/http_sse/components/task_logger_forwarder.py +109 -0
  210. solace_agent_mesh/gateway/http_sse/components/visualization_forwarder_component.py +4 -2
  211. solace_agent_mesh/gateway/http_sse/dependencies.py +119 -27
  212. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +172 -172
  213. solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +3278 -0
  214. solace_agent_mesh/gateway/http_sse/main.py +149 -42
  215. solace_agent_mesh/gateway/http_sse/repository/__init__.py +3 -12
  216. solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +103 -0
  217. solace_agent_mesh/gateway/http_sse/repository/entities/__init__.py +5 -3
  218. solace_agent_mesh/gateway/http_sse/repository/entities/chat_task.py +75 -0
  219. solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +263 -0
  220. solace_agent_mesh/gateway/http_sse/repository/entities/feedback.py +20 -0
  221. solace_agent_mesh/gateway/http_sse/repository/entities/session_history.py +0 -16
  222. solace_agent_mesh/gateway/http_sse/repository/entities/task.py +25 -0
  223. solace_agent_mesh/gateway/http_sse/repository/entities/task_event.py +21 -0
  224. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +81 -0
  225. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +73 -18
  226. solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +9 -5
  227. solace_agent_mesh/gateway/http_sse/repository/models/chat_task_model.py +31 -0
  228. solace_agent_mesh/gateway/http_sse/repository/models/feedback_model.py +21 -0
  229. solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +266 -0
  230. solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +3 -3
  231. solace_agent_mesh/gateway/http_sse/repository/models/task_event_model.py +25 -0
  232. solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +32 -0
  233. solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +340 -0
  234. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +4 -53
  235. solace_agent_mesh/gateway/http_sse/repository/task_repository.py +173 -0
  236. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +3 -2
  237. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +3 -3
  238. solace_agent_mesh/gateway/http_sse/routers/auth.py +3 -1
  239. solace_agent_mesh/gateway/http_sse/routers/config.py +29 -6
  240. solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +346 -0
  241. solace_agent_mesh/gateway/http_sse/routers/dto/requests/__init__.py +3 -3
  242. solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +83 -0
  243. solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +2 -10
  244. solace_agent_mesh/gateway/http_sse/routers/dto/requests/task_requests.py +58 -0
  245. solace_agent_mesh/gateway/http_sse/routers/dto/responses/__init__.py +5 -3
  246. solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +107 -0
  247. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +1 -15
  248. solace_agent_mesh/gateway/http_sse/routers/dto/responses/task_responses.py +30 -0
  249. solace_agent_mesh/gateway/http_sse/routers/feedback.py +37 -0
  250. solace_agent_mesh/gateway/http_sse/routers/people.py +3 -1
  251. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +255 -204
  252. solace_agent_mesh/gateway/http_sse/routers/sessions.py +223 -41
  253. solace_agent_mesh/gateway/http_sse/routers/sse.py +3 -2
  254. solace_agent_mesh/gateway/http_sse/routers/tasks.py +170 -43
  255. solace_agent_mesh/gateway/http_sse/routers/users.py +3 -1
  256. solace_agent_mesh/gateway/http_sse/routers/visualization.py +2 -1
  257. solace_agent_mesh/gateway/http_sse/services/agent_card_service.py +3 -1
  258. solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +273 -0
  259. solace_agent_mesh/gateway/http_sse/services/feedback_service.py +242 -0
  260. solace_agent_mesh/gateway/http_sse/services/people_service.py +2 -82
  261. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +177 -13
  262. solace_agent_mesh/gateway/http_sse/services/session_service.py +154 -85
  263. solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +318 -0
  264. solace_agent_mesh/gateway/http_sse/services/task_service.py +3 -2
  265. solace_agent_mesh/gateway/http_sse/session_manager.py +2 -1
  266. solace_agent_mesh/gateway/http_sse/shared/exception_handlers.py +25 -14
  267. solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +285 -0
  268. solace_agent_mesh/gateway/http_sse/shared/types.py +7 -0
  269. solace_agent_mesh/gateway/http_sse/sse_event_buffer.py +2 -1
  270. solace_agent_mesh/gateway/http_sse/sse_manager.py +2 -2
  271. solace_agent_mesh/gateway/http_sse/utils/__init__.py +1 -0
  272. solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +32 -0
  273. solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +47 -0
  274. solace_agent_mesh/solace_agent_mesh_llm.txt +1 -1
  275. solace_agent_mesh/solace_agent_mesh_llm_detail.txt +8599 -0
  276. solace_agent_mesh/templates/gateway_app_template.py +4 -2
  277. solace_agent_mesh/templates/gateway_component_template.py +3 -1
  278. solace_agent_mesh/templates/logging_config_template.ini +22 -45
  279. solace_agent_mesh/templates/plugin_tools_template.py +2 -2
  280. {solace_agent_mesh-1.4.12.dist-info → solace_agent_mesh-1.5.1.dist-info}/METADATA +2 -2
  281. solace_agent_mesh-1.5.1.dist-info/RECORD +504 -0
  282. solace_agent_mesh/agent/adk/invocation_monitor.py +0 -295
  283. solace_agent_mesh/assets/docs/assets/images/sac-flows-80d5b603c6aafd33e87945680ce0abf3.png +0 -0
  284. solace_agent_mesh/assets/docs/assets/images/sac_parts_of_a_component-cb3d0424b1d0c17734c5435cca6b4082.png +0 -0
  285. solace_agent_mesh/assets/docs/assets/js/04989206.a248f00c.js +0 -1
  286. solace_agent_mesh/assets/docs/assets/js/0e682baa.d54b8668.js +0 -1
  287. solace_agent_mesh/assets/docs/assets/js/1023fc19.8a8a9309.js +0 -1
  288. solace_agent_mesh/assets/docs/assets/js/1523c6b4.2645ef68.js +0 -1
  289. solace_agent_mesh/assets/docs/assets/js/166ab619.e27886d9.js +0 -1
  290. solace_agent_mesh/assets/docs/assets/js/1c6e87d2.e056b7e0.js +0 -1
  291. solace_agent_mesh/assets/docs/assets/js/21ceee5f.3bf39250.js +0 -1
  292. solace_agent_mesh/assets/docs/assets/js/2a9cab12.2afaee76.js +0 -1
  293. solace_agent_mesh/assets/docs/assets/js/332e10b5.f7629851.js +0 -1
  294. solace_agent_mesh/assets/docs/assets/js/3d406171.5560fdf9.js +0 -1
  295. solace_agent_mesh/assets/docs/assets/js/42b3f8d8.508ae8db.js +0 -1
  296. solace_agent_mesh/assets/docs/assets/js/442a8107.b5c2532a.js +0 -1
  297. solace_agent_mesh/assets/docs/assets/js/453a82a6.3c6bb61d.js +0 -1
  298. solace_agent_mesh/assets/docs/assets/js/483cef9a.4736f2d8.js +0 -1
  299. solace_agent_mesh/assets/docs/assets/js/4c2787c2.c1290a40.js +0 -1
  300. solace_agent_mesh/assets/docs/assets/js/55f47984.bcd00a86.js +0 -1
  301. solace_agent_mesh/assets/docs/assets/js/5b4258a4.fdfd2325.js +0 -1
  302. solace_agent_mesh/assets/docs/assets/js/664b740a.ba305a89.js +0 -1
  303. solace_agent_mesh/assets/docs/assets/js/75384d09.c19e8b51.js +0 -1
  304. solace_agent_mesh/assets/docs/assets/js/768e31b0.9abcdc48.js +0 -1
  305. solace_agent_mesh/assets/docs/assets/js/85387663.be2bc838.js +0 -1
  306. solace_agent_mesh/assets/docs/assets/js/945fb41e.16e00776.js +0 -1
  307. solace_agent_mesh/assets/docs/assets/js/9a09e75d.92de8cf5.js +0 -1
  308. solace_agent_mesh/assets/docs/assets/js/9eff14a2.d62aad71.js +0 -1
  309. solace_agent_mesh/assets/docs/assets/js/a12a4955.25fbed32.js +0 -1
  310. solace_agent_mesh/assets/docs/assets/js/a3a92b25.af35e313.js +0 -1
  311. solace_agent_mesh/assets/docs/assets/js/aba87c2f.4ddf32f2.js +0 -1
  312. solace_agent_mesh/assets/docs/assets/js/ae0e903d.5fe5203f.js +0 -1
  313. solace_agent_mesh/assets/docs/assets/js/ae4415af.16cc58d3.js +0 -1
  314. solace_agent_mesh/assets/docs/assets/js/bac0be12.17de4316.js +0 -1
  315. solace_agent_mesh/assets/docs/assets/js/c2c06897.87cb1f47.js +0 -1
  316. solace_agent_mesh/assets/docs/assets/js/c835a94d.ce21f0bf.js +0 -1
  317. solace_agent_mesh/assets/docs/assets/js/cc969b05.feef7dcc.js +0 -1
  318. solace_agent_mesh/assets/docs/assets/js/cd3d4052.a19e7d78.js +0 -1
  319. solace_agent_mesh/assets/docs/assets/js/ced92a13.fb92e7ca.js +0 -1
  320. solace_agent_mesh/assets/docs/assets/js/cee5d587.47904f5e.js +0 -1
  321. solace_agent_mesh/assets/docs/assets/js/d6a81ee7.829198f1.js +0 -1
  322. solace_agent_mesh/assets/docs/assets/js/f284c35a.ed8dd236.js +0 -1
  323. solace_agent_mesh/assets/docs/assets/js/f897a61a.126663fe.js +0 -1
  324. solace_agent_mesh/assets/docs/assets/js/fbfa3e75.e144b16c.js +0 -1
  325. solace_agent_mesh/assets/docs/assets/js/main.f67fc9f4.js +0 -2
  326. solace_agent_mesh/assets/docs/assets/js/runtime~main.40527046.js +0 -1
  327. solace_agent_mesh/assets/docs/docs/documentation/Enterprise/installation/index.html +0 -46
  328. solace_agent_mesh/assets/docs/docs/documentation/Enterprise/rbac-setup-guilde/index.html +0 -201
  329. solace_agent_mesh/assets/docs/docs/documentation/Enterprise/single-sign-on/index.html +0 -25
  330. solace_agent_mesh/assets/docs/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0/index.html +0 -105
  331. solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +0 -144
  332. solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +0 -91
  333. solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +0 -91
  334. solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +0 -55
  335. solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +0 -111
  336. solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +0 -77
  337. solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +0 -48
  338. solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +0 -54
  339. solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +0 -45
  340. solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/litellm_models/index.html +0 -49
  341. solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +0 -76
  342. solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +0 -73
  343. solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +0 -72
  344. solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +0 -54
  345. solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +0 -69
  346. solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +0 -59
  347. solace_agent_mesh/assets/docs/lunr-index-1759936913198.json +0 -1
  348. solace_agent_mesh/assets/docs/search-doc-1759936913198.json +0 -1
  349. solace_agent_mesh/client/webui/frontend/static/assets/main-ChRwcV89.css +0 -1
  350. solace_agent_mesh/client/webui/frontend/static/assets/main-DnnE01OM.js +0 -339
  351. solace_agent_mesh/gateway/http_sse/repository/entities/message.py +0 -41
  352. solace_agent_mesh/gateway/http_sse/repository/message_repository.py +0 -84
  353. solace_agent_mesh/gateway/http_sse/repository/models/message_model.py +0 -45
  354. solace_agent_mesh-1.4.12.dist-info/RECORD +0 -448
  355. /solace_agent_mesh/assets/docs/assets/js/{8591.d7c16be6.js.LICENSE.txt → 8591.5d015485.js.LICENSE.txt} +0 -0
  356. /solace_agent_mesh/assets/docs/assets/js/{main.f67fc9f4.js.LICENSE.txt → main.bd3c34f3.js.LICENSE.txt} +0 -0
  357. {solace_agent_mesh-1.4.12.dist-info → solace_agent_mesh-1.5.1.dist-info}/WHEEL +0 -0
  358. {solace_agent_mesh-1.4.12.dist-info → solace_agent_mesh-1.5.1.dist-info}/entry_points.txt +0 -0
  359. {solace_agent_mesh-1.4.12.dist-info → solace_agent_mesh-1.5.1.dist-info}/licenses/LICENSE +0 -0
@@ -2,20 +2,28 @@
2
2
  API Router for submitting and managing tasks to agents.
3
3
  """
4
4
 
5
+ import logging
6
+ import yaml
7
+ from datetime import datetime
5
8
  from fastapi import (
6
9
  APIRouter,
7
10
  Depends,
8
11
  HTTPException,
9
12
  Request as FastAPIRequest,
13
+ Response,
10
14
  status,
11
15
  )
12
- from typing import Union
16
+ from fastapi.exceptions import RequestValidationError
17
+ from typing import List, Optional, Union
13
18
 
14
- from solace_ai_connector.common.log import log
15
19
 
16
20
  from ....gateway.http_sse.session_manager import SessionManager
17
21
  from ....gateway.http_sse.services.task_service import TaskService
18
22
  from ....gateway.http_sse.services.session_service import SessionService
23
+ from ....gateway.http_sse.repository.interfaces import ITaskRepository
24
+ from ....gateway.http_sse.repository.entities import Task
25
+ from ....gateway.http_sse.shared.types import PaginationParams, UserId
26
+ from ..utils.stim_utils import create_stim_from_task_data
19
27
 
20
28
  from a2a.types import (
21
29
  CancelTaskRequest,
@@ -31,7 +39,12 @@ from ....gateway.http_sse.dependencies import (
31
39
  get_sac_component,
32
40
  get_task_service,
33
41
  get_session_business_service,
42
+ get_task_repository,
43
+ get_user_id,
44
+ get_user_config,
45
+ get_session_business_service,
34
46
  )
47
+ from ....gateway.http_sse.services.session_service import SessionService
35
48
 
36
49
  from typing import TYPE_CHECKING
37
50
 
@@ -40,6 +53,7 @@ if TYPE_CHECKING:
40
53
 
41
54
  router = APIRouter()
42
55
 
56
+ log = logging.getLogger(__name__)
43
57
 
44
58
  async def _submit_task(
45
59
  request: FastAPIRequest,
@@ -58,7 +72,7 @@ async def _submit_task(
58
72
 
59
73
  if not agent_name:
60
74
  raise HTTPException(
61
- status_code=status.HTTP_400_BAD_REQUEST,
75
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
62
76
  detail="Missing 'agent_name' in request payload message metadata.",
63
77
  )
64
78
 
@@ -120,10 +134,14 @@ async def _submit_task(
120
134
  session_id=session_id,
121
135
  )
122
136
  db.commit()
123
- log.info("%sCreated session in database: %s", log_prefix, session_id)
137
+ log.info(
138
+ "%sCreated session in database: %s", log_prefix, session_id
139
+ )
124
140
  except Exception as e:
125
141
  db.rollback()
126
- log.warning("%sFailed to create session in database: %s", log_prefix, e)
142
+ log.warning(
143
+ "%sFailed to create session in database: %s", log_prefix, e
144
+ )
127
145
  finally:
128
146
  db.close()
129
147
 
@@ -131,43 +149,6 @@ async def _submit_task(
131
149
  "%sUsing ClientID: %s, SessionID: %s", log_prefix, client_id, session_id
132
150
  )
133
151
 
134
- # Store message in persistence layer if available
135
- if is_streaming and SessionLocal is not None and session_service is not None:
136
- db = SessionLocal()
137
- try:
138
- from ....gateway.http_sse.shared.enums import SenderType
139
-
140
- message_text = ""
141
- if payload.params and payload.params.message:
142
- parts = a2a.get_parts_from_message(payload.params.message)
143
- for part in parts:
144
- if hasattr(part, "text"):
145
- message_text = part.text
146
- break
147
-
148
- session_service.add_message_to_session(
149
- db=db,
150
- session_id=session_id,
151
- user_id=user_id,
152
- message=message_text or "Task submitted",
153
- sender_type=SenderType.USER,
154
- sender_name=user_id or "user",
155
- agent_id=agent_name,
156
- )
157
- db.commit()
158
- except Exception as e:
159
- db.rollback()
160
- log.error(
161
- "%sFailed to store message in session service: %s", log_prefix, e
162
- )
163
- finally:
164
- db.close()
165
- else:
166
- log.debug(
167
- "%sNo persistence available or non-streaming - skipping message storage",
168
- log_prefix,
169
- )
170
-
171
152
  # Use the helper to get the unwrapped parts from the incoming message.
172
153
  a2a_parts = a2a.get_parts_from_message(payload.params.message)
173
154
 
@@ -222,6 +203,146 @@ async def _submit_task(
222
203
  )
223
204
 
224
205
 
206
+ @router.get("/tasks", response_model=List[Task], tags=["Tasks"])
207
+ async def search_tasks(
208
+ request: FastAPIRequest,
209
+ start_date: Optional[str] = None,
210
+ end_date: Optional[str] = None,
211
+ search: Optional[str] = None,
212
+ page: int = 1,
213
+ page_size: int = 20,
214
+ query_user_id: Optional[str] = None,
215
+ user_id: UserId = Depends(get_user_id),
216
+ user_config: dict = Depends(get_user_config),
217
+ repo: ITaskRepository = Depends(get_task_repository),
218
+ ):
219
+ """
220
+ Lists and searches for historical tasks.
221
+ - Regular users can only search their own tasks.
222
+ - Users with the 'tasks:read:all' scope can search for any user's tasks by providing `query_user_id`.
223
+ """
224
+ log_prefix = f"[GET /api/v1/tasks] "
225
+ log.info("%sRequest from user %s", log_prefix, user_id)
226
+
227
+ target_user_id = user_id
228
+ can_query_all = user_config.get("scopes", {}).get("tasks:read:all", False)
229
+
230
+ if query_user_id:
231
+ if can_query_all:
232
+ target_user_id = query_user_id
233
+ log.info(
234
+ "%sAdmin user %s is querying for user %s",
235
+ log_prefix,
236
+ user_id,
237
+ target_user_id,
238
+ )
239
+ else:
240
+ raise HTTPException(
241
+ status_code=status.HTTP_403_FORBIDDEN,
242
+ detail="You do not have permission to query for other users' tasks.",
243
+ )
244
+ elif can_query_all:
245
+ target_user_id = "*"
246
+ log.info("%sAdmin user %s is querying for all users.", log_prefix, user_id)
247
+
248
+ start_time_ms = None
249
+ if start_date:
250
+ try:
251
+ start_time_ms = int(datetime.fromisoformat(start_date).timestamp() * 1000)
252
+ except ValueError:
253
+ raise HTTPException(
254
+ status_code=status.HTTP_400_BAD_REQUEST,
255
+ detail="Invalid start_date format. Use ISO 8601 format.",
256
+ )
257
+
258
+ end_time_ms = None
259
+ if end_date:
260
+ try:
261
+ end_time_ms = int(datetime.fromisoformat(end_date).timestamp() * 1000)
262
+ except ValueError:
263
+ raise HTTPException(
264
+ status_code=status.HTTP_400_BAD_REQUEST,
265
+ detail="Invalid end_date format. Use ISO 8601 format.",
266
+ )
267
+
268
+ pagination = PaginationParams(page=page, page_size=page_size)
269
+
270
+ try:
271
+ tasks = repo.search(
272
+ user_id=target_user_id,
273
+ start_date=start_time_ms,
274
+ end_date=end_time_ms,
275
+ search_query=search,
276
+ pagination=pagination,
277
+ )
278
+ return tasks
279
+ except Exception as e:
280
+ log.exception("%sError searching for tasks: %s", log_prefix, e)
281
+ raise HTTPException(
282
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
283
+ detail="An error occurred while searching for tasks.",
284
+ )
285
+
286
+
287
+ @router.get("/tasks/{task_id}", tags=["Tasks"])
288
+ async def get_task_as_stim_file(
289
+ task_id: str,
290
+ request: FastAPIRequest,
291
+ user_id: UserId = Depends(get_user_id),
292
+ user_config: dict = Depends(get_user_config),
293
+ repo: ITaskRepository = Depends(get_task_repository),
294
+ ):
295
+ """
296
+ Retrieves the complete event history for a single task and returns it as a `.stim` file.
297
+ """
298
+ log_prefix = f"[GET /api/v1/tasks/{task_id}] "
299
+ log.info("%sRequest from user %s", log_prefix, user_id)
300
+
301
+ try:
302
+ result = repo.find_by_id_with_events(task_id)
303
+ if not result:
304
+ raise HTTPException(
305
+ status_code=status.HTTP_404_NOT_FOUND,
306
+ detail=f"Task with ID '{task_id}' not found.",
307
+ )
308
+
309
+ task, events = result
310
+
311
+ can_read_all = user_config.get("scopes", {}).get("tasks:read:all", False)
312
+ if task.user_id != user_id and not can_read_all:
313
+ raise HTTPException(
314
+ status_code=status.HTTP_403_FORBIDDEN,
315
+ detail="You do not have permission to view this task.",
316
+ )
317
+
318
+ # Format into .stim structure
319
+ stim_data = create_stim_from_task_data(task, events)
320
+
321
+ yaml_content = yaml.dump(
322
+ stim_data,
323
+ sort_keys=False,
324
+ allow_unicode=True,
325
+ indent=2,
326
+ default_flow_style=False,
327
+ )
328
+
329
+ return Response(
330
+ content=yaml_content,
331
+ media_type="application/x-yaml",
332
+ headers={"Content-Disposition": f'attachment; filename="{task_id}.stim"'},
333
+ )
334
+
335
+ except HTTPException:
336
+ # Re-raise HTTPExceptions (404, 403, etc.) without modification
337
+ raise
338
+ except Exception as e:
339
+ log.exception("%sError retrieving task: %s", log_prefix, e)
340
+ raise HTTPException(
341
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
342
+ detail="An error occurred while retrieving the task.",
343
+ )
344
+
345
+
225
346
  @router.post("/message:send", response_model=SendMessageSuccessResponse)
226
347
  async def send_task_to_agent(
227
348
  request: FastAPIRequest,
@@ -278,6 +399,7 @@ async def cancel_agent_task(
278
399
  """
279
400
  Sends a cancellation request for a specific task to the specified agent.
280
401
  Returns 202 Accepted, as cancellation is asynchronous.
402
+ Returns 404 if the task context is not found.
281
403
  """
282
404
  log_prefix = f"[POST /api/v1/tasks/{taskId}:cancel] "
283
405
  log.info("%sReceived cancellation request.", log_prefix)
@@ -290,6 +412,11 @@ async def cancel_agent_task(
290
412
 
291
413
  context = component.task_context_manager.get_context(taskId)
292
414
  if not context:
415
+ log.warning(
416
+ "%sNo active task context found for task ID: %s",
417
+ log_prefix,
418
+ taskId,
419
+ )
293
420
  raise HTTPException(
294
421
  status_code=status.HTTP_404_NOT_FOUND,
295
422
  detail=f"No active task context found for task ID: {taskId}",
@@ -328,4 +455,4 @@ async def cancel_agent_task(
328
455
  raise HTTPException(
329
456
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
330
457
  detail=error_resp.model_dump(exclude_none=True),
331
- )
458
+ )
@@ -3,13 +3,15 @@ Router for user-related endpoints.
3
3
  Maintains backward compatibility with original API format.
4
4
  """
5
5
 
6
+ import logging
6
7
  from typing import Any
7
8
 
8
9
  from fastapi import APIRouter, Depends
9
- from solace_ai_connector.common.log import log
10
10
 
11
11
  from ..shared.auth_utils import get_current_user
12
12
 
13
+ log = logging.getLogger(__name__)
14
+
13
15
  router = APIRouter()
14
16
 
15
17
 
@@ -2,6 +2,7 @@
2
2
  API Router for managing A2A message visualization streams.
3
3
  """
4
4
 
5
+ import logging
5
6
  import asyncio
6
7
  import uuid
7
8
  from fastapi import (
@@ -15,7 +16,6 @@ from fastapi import (
15
16
  from pydantic import BaseModel, Field
16
17
  from typing import List, Optional, Dict, Any, Set
17
18
 
18
- from solace_ai_connector.common.log import log
19
19
 
20
20
  from ....gateway.http_sse.dependencies import (
21
21
  get_sac_component,
@@ -30,6 +30,7 @@ from typing import TYPE_CHECKING
30
30
  if TYPE_CHECKING:
31
31
  from ....gateway.http_sse.component import WebUIBackendComponent
32
32
 
33
+ log = logging.getLogger(__name__)
33
34
 
34
35
  router = APIRouter()
35
36
 
@@ -5,7 +5,9 @@ with the AgentRegistry.
5
5
 
6
6
  from typing import List, Optional
7
7
 
8
- from solace_ai_connector.common.log import log
8
+ import logging
9
+
10
+ log = logging.getLogger(__name__)
9
11
 
10
12
  from ....common.agent_registry import AgentRegistry
11
13
  from a2a.types import AgentCard
@@ -0,0 +1,273 @@
1
+ """
2
+ Service for managing automatic cleanup of old data based on retention policies.
3
+ """
4
+
5
+ import logging
6
+ import time
7
+ from typing import Any, Callable, Dict
8
+
9
+ from sqlalchemy.orm import Session as DBSession
10
+
11
+ from ..repository.feedback_repository import FeedbackRepository
12
+ from ..repository.task_repository import TaskRepository
13
+ from ..shared import now_epoch_ms
14
+
15
+ log = logging.getLogger(__name__)
16
+
17
+ class DataRetentionService:
18
+ """
19
+ Service for automatically cleaning up old tasks, task events, and feedback
20
+ based on configurable retention policies.
21
+ """
22
+
23
+ # Validation constants
24
+ MIN_RETENTION_DAYS = 1
25
+ MIN_CLEANUP_INTERVAL_HOURS = 1
26
+ MIN_BATCH_SIZE = 1
27
+ MAX_BATCH_SIZE = 10000
28
+
29
+ def __init__(
30
+ self, session_factory: Callable[[], DBSession] | None, config: Dict[str, Any]
31
+ ):
32
+ """
33
+ Initialize the DataRetentionService.
34
+
35
+ Args:
36
+ session_factory: Factory function to create database sessions
37
+ config: Configuration dictionary with retention settings
38
+ """
39
+ self.session_factory = session_factory
40
+ self.config = config
41
+ self.log_identifier = "[DataRetentionService]"
42
+
43
+ # Validate and store configuration
44
+ self._validate_config()
45
+
46
+ log.info(
47
+ "%s Initialized with task_retention=%d days, feedback_retention=%d days, "
48
+ "cleanup_interval=%d hours, batch_size=%d",
49
+ self.log_identifier,
50
+ self.config.get("task_retention_days"),
51
+ self.config.get("feedback_retention_days"),
52
+ self.config.get("cleanup_interval_hours"),
53
+ self.config.get("batch_size"),
54
+ )
55
+
56
+ def _validate_config(self) -> None:
57
+ """
58
+ Validates configuration values and applies safe defaults if needed.
59
+ Logs warnings for invalid values.
60
+ """
61
+ # Validate task retention days
62
+ task_retention = self.config.get("task_retention_days", 90)
63
+ if task_retention < self.MIN_RETENTION_DAYS:
64
+ log.warning(
65
+ "%s task_retention_days (%d) is below minimum (%d days). Using minimum.",
66
+ self.log_identifier,
67
+ task_retention,
68
+ self.MIN_RETENTION_DAYS,
69
+ )
70
+ self.config["task_retention_days"] = self.MIN_RETENTION_DAYS
71
+ else:
72
+ self.config["task_retention_days"] = task_retention
73
+
74
+ # Validate feedback retention days
75
+ feedback_retention = self.config.get("feedback_retention_days", 90)
76
+ if feedback_retention < self.MIN_RETENTION_DAYS:
77
+ log.warning(
78
+ "%s feedback_retention_days (%d) is below minimum (%d days). Using minimum.",
79
+ self.log_identifier,
80
+ feedback_retention,
81
+ self.MIN_RETENTION_DAYS,
82
+ )
83
+ self.config["feedback_retention_days"] = self.MIN_RETENTION_DAYS
84
+ else:
85
+ self.config["feedback_retention_days"] = feedback_retention
86
+
87
+ # Validate cleanup interval
88
+ cleanup_interval = self.config.get("cleanup_interval_hours", 24)
89
+ if cleanup_interval < self.MIN_CLEANUP_INTERVAL_HOURS:
90
+ log.warning(
91
+ "%s cleanup_interval_hours (%d) is below minimum (%d hours). Using minimum.",
92
+ self.log_identifier,
93
+ cleanup_interval,
94
+ self.MIN_CLEANUP_INTERVAL_HOURS,
95
+ )
96
+ self.config["cleanup_interval_hours"] = self.MIN_CLEANUP_INTERVAL_HOURS
97
+ else:
98
+ self.config["cleanup_interval_hours"] = cleanup_interval
99
+
100
+ # Validate batch size
101
+ batch_size = self.config.get("batch_size", 1000)
102
+ if batch_size < self.MIN_BATCH_SIZE:
103
+ log.warning(
104
+ "%s batch_size (%d) is below minimum (%d). Using minimum.",
105
+ self.log_identifier,
106
+ batch_size,
107
+ self.MIN_BATCH_SIZE,
108
+ )
109
+ self.config["batch_size"] = self.MIN_BATCH_SIZE
110
+ elif batch_size > self.MAX_BATCH_SIZE:
111
+ log.warning(
112
+ "%s batch_size (%d) exceeds maximum (%d). Using maximum.",
113
+ self.log_identifier,
114
+ batch_size,
115
+ self.MAX_BATCH_SIZE,
116
+ )
117
+ self.config["batch_size"] = self.MAX_BATCH_SIZE
118
+ else:
119
+ self.config["batch_size"] = batch_size
120
+
121
+ def cleanup_old_data(self) -> None:
122
+ """
123
+ Main orchestration method for cleaning up old data.
124
+ Calls cleanup methods for tasks and feedback.
125
+ """
126
+ if not self.config.get("enabled", True):
127
+ log.warning(
128
+ "%s Data retention cleanup is disabled via configuration.",
129
+ self.log_identifier,
130
+ )
131
+ return
132
+
133
+ if not self.session_factory:
134
+ log.warning(
135
+ "%s No database session factory available. Skipping cleanup.",
136
+ self.log_identifier,
137
+ )
138
+ return
139
+
140
+ log.info("%s Starting data retention cleanup...", self.log_identifier)
141
+ start_time = time.time()
142
+
143
+ try:
144
+ # Cleanup old tasks
145
+ task_retention_days = self.config.get("task_retention_days")
146
+ tasks_deleted = self._cleanup_old_tasks(task_retention_days)
147
+
148
+ # Cleanup old feedback
149
+ feedback_retention_days = self.config.get("feedback_retention_days")
150
+ feedback_deleted = self._cleanup_old_feedback(feedback_retention_days)
151
+
152
+ elapsed_time = time.time() - start_time
153
+ log.info(
154
+ "%s Cleanup completed. Tasks deleted: %d, Feedback deleted: %d, Time taken: %.2f seconds",
155
+ self.log_identifier,
156
+ tasks_deleted,
157
+ feedback_deleted,
158
+ elapsed_time,
159
+ )
160
+
161
+ except Exception as e:
162
+ log.error(
163
+ "%s Error during data retention cleanup: %s",
164
+ self.log_identifier,
165
+ e,
166
+ exc_info=True,
167
+ )
168
+
169
+ def _cleanup_old_tasks(self, retention_days: int) -> int:
170
+ """
171
+ Deletes tasks (and their events via cascade) older than the retention period.
172
+
173
+ Args:
174
+ retention_days: Number of days to retain tasks
175
+
176
+ Returns:
177
+ Total number of tasks deleted
178
+ """
179
+ log.info(
180
+ "%s Cleaning up tasks older than %d days...",
181
+ self.log_identifier,
182
+ retention_days,
183
+ )
184
+
185
+ # Calculate cutoff time in milliseconds
186
+ cutoff_time_ms = now_epoch_ms() - (retention_days * 24 * 60 * 60 * 1000)
187
+ batch_size = self.config.get("batch_size")
188
+
189
+ db = self.session_factory()
190
+ try:
191
+ repo = TaskRepository(db)
192
+ total_deleted = repo.delete_tasks_older_than(cutoff_time_ms, batch_size)
193
+
194
+ if total_deleted == 0:
195
+ log.info(
196
+ "%s No tasks found older than %d days.",
197
+ self.log_identifier,
198
+ retention_days,
199
+ )
200
+ else:
201
+ log.info(
202
+ "%s Deleted %d tasks older than %d days.",
203
+ self.log_identifier,
204
+ total_deleted,
205
+ retention_days,
206
+ )
207
+
208
+ return total_deleted
209
+
210
+ except Exception as e:
211
+ log.error(
212
+ "%s Error cleaning up old tasks: %s",
213
+ self.log_identifier,
214
+ e,
215
+ exc_info=True,
216
+ )
217
+ db.rollback()
218
+ return 0
219
+ finally:
220
+ db.close()
221
+
222
+ def _cleanup_old_feedback(self, retention_days: int) -> int:
223
+ """
224
+ Deletes feedback records older than the retention period.
225
+
226
+ Args:
227
+ retention_days: Number of days to retain feedback
228
+
229
+ Returns:
230
+ Total number of feedback records deleted
231
+ """
232
+ log.info(
233
+ "%s Cleaning up feedback older than %d days...",
234
+ self.log_identifier,
235
+ retention_days,
236
+ )
237
+
238
+ # Calculate cutoff time in milliseconds
239
+ cutoff_time_ms = now_epoch_ms() - (retention_days * 24 * 60 * 60 * 1000)
240
+ batch_size = self.config.get("batch_size")
241
+
242
+ db = self.session_factory()
243
+ try:
244
+ repo = FeedbackRepository(db)
245
+ total_deleted = repo.delete_feedback_older_than(cutoff_time_ms, batch_size)
246
+
247
+ if total_deleted == 0:
248
+ log.info(
249
+ "%s No feedback found older than %d days.",
250
+ self.log_identifier,
251
+ retention_days,
252
+ )
253
+ else:
254
+ log.info(
255
+ "%s Deleted %d feedback records older than %d days.",
256
+ self.log_identifier,
257
+ total_deleted,
258
+ retention_days,
259
+ )
260
+
261
+ return total_deleted
262
+
263
+ except Exception as e:
264
+ log.error(
265
+ "%s Error cleaning up old feedback: %s",
266
+ self.log_identifier,
267
+ e,
268
+ exc_info=True,
269
+ )
270
+ db.rollback()
271
+ return 0
272
+ finally:
273
+ db.close()