solace-agent-mesh 1.0.9__py3-none-any.whl → 1.3.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 (220) hide show
  1. solace_agent_mesh/agent/adk/adk_llm.txt +182 -42
  2. solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +171 -0
  3. solace_agent_mesh/agent/adk/callbacks.py +165 -104
  4. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +0 -18
  5. solace_agent_mesh/agent/adk/models/models_llm.txt +104 -55
  6. solace_agent_mesh/agent/adk/runner.py +25 -17
  7. solace_agent_mesh/agent/adk/services.py +3 -3
  8. solace_agent_mesh/agent/adk/setup.py +11 -0
  9. solace_agent_mesh/agent/adk/stream_parser.py +8 -1
  10. solace_agent_mesh/agent/adk/tool_wrapper.py +10 -3
  11. solace_agent_mesh/agent/agent_llm.txt +355 -18
  12. solace_agent_mesh/agent/protocol/event_handlers.py +460 -317
  13. solace_agent_mesh/agent/protocol/protocol_llm.txt +54 -7
  14. solace_agent_mesh/agent/sac/app.py +2 -2
  15. solace_agent_mesh/agent/sac/component.py +211 -517
  16. solace_agent_mesh/agent/sac/sac_llm.txt +133 -63
  17. solace_agent_mesh/agent/testing/testing_llm.txt +25 -58
  18. solace_agent_mesh/agent/tools/peer_agent_tool.py +15 -11
  19. solace_agent_mesh/agent/tools/tools_llm.txt +234 -69
  20. solace_agent_mesh/agent/utils/artifact_helpers.py +35 -1
  21. solace_agent_mesh/agent/utils/utils_llm.txt +90 -105
  22. solace_agent_mesh/assets/docs/404.html +3 -3
  23. solace_agent_mesh/assets/docs/assets/js/6e0db977.39a79ca9.js +1 -0
  24. solace_agent_mesh/assets/docs/assets/js/{75384d09.ccd480c4.js → 75384d09.bf78fbdb.js} +1 -1
  25. solace_agent_mesh/assets/docs/assets/js/90dd9cf6.88f385ea.js +1 -0
  26. solace_agent_mesh/assets/docs/assets/js/f284c35a.fb68323a.js +1 -0
  27. solace_agent_mesh/assets/docs/assets/js/main.08d30374.js +2 -0
  28. solace_agent_mesh/assets/docs/assets/js/runtime~main.458efb1d.js +1 -0
  29. solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +4 -4
  30. solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +4 -4
  31. solace_agent_mesh/assets/docs/docs/documentation/concepts/cli/index.html +4 -4
  32. solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +4 -4
  33. solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +4 -4
  34. solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +4 -4
  35. solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +4 -4
  36. solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +4 -4
  37. solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +4 -4
  38. solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +4 -4
  39. solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/index.html +4 -4
  40. solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +4 -4
  41. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +4 -4
  42. solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +4 -4
  43. solace_agent_mesh/assets/docs/docs/documentation/migration-guides/a2a-upgrade-to-0.3.0/a2a-gateway-upgrade-to-0.3.0/index.html +105 -0
  44. solace_agent_mesh/assets/docs/docs/documentation/migration-guides/a2a-upgrade-to-0.3.0/a2a-technical-migration-map/index.html +53 -0
  45. solace_agent_mesh/assets/docs/docs/documentation/tutorials/bedrock-agents/index.html +4 -4
  46. solace_agent_mesh/assets/docs/docs/documentation/tutorials/custom-agent/index.html +4 -4
  47. solace_agent_mesh/assets/docs/docs/documentation/tutorials/event-mesh-gateway/index.html +4 -4
  48. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mcp-integration/index.html +4 -4
  49. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mongodb-integration/index.html +4 -4
  50. solace_agent_mesh/assets/docs/docs/documentation/tutorials/rag-integration/index.html +4 -4
  51. solace_agent_mesh/assets/docs/docs/documentation/tutorials/rest-gateway/index.html +4 -4
  52. solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +4 -4
  53. solace_agent_mesh/assets/docs/docs/documentation/tutorials/sql-database/index.html +4 -4
  54. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/artifact-management/index.html +4 -4
  55. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/audio-tools/index.html +4 -4
  56. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/data-analysis-tools/index.html +4 -4
  57. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/embeds/index.html +4 -4
  58. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/index.html +4 -4
  59. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-agents/index.html +4 -4
  60. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-gateways/index.html +4 -4
  61. solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +4 -4
  62. solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +4 -4
  63. solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +4 -4
  64. solace_agent_mesh/assets/docs/lunr-index-1757433031159.json +1 -0
  65. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  66. solace_agent_mesh/assets/docs/search-doc-1757433031159.json +1 -0
  67. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  68. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  69. solace_agent_mesh/cli/__init__.py +1 -1
  70. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +125 -48
  71. solace_agent_mesh/cli/commands/eval_cmd.py +14 -0
  72. solace_agent_mesh/cli/commands/init_cmd/__init__.py +53 -31
  73. solace_agent_mesh/cli/commands/init_cmd/database_step.py +91 -0
  74. solace_agent_mesh/cli/commands/init_cmd/env_step.py +19 -8
  75. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +80 -25
  76. solace_agent_mesh/cli/commands/init_cmd/web_init_step.py +32 -10
  77. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +74 -15
  78. solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +0 -2
  79. solace_agent_mesh/cli/commands/run_cmd.py +5 -3
  80. solace_agent_mesh/cli/utils.py +68 -12
  81. solace_agent_mesh/client/webui/frontend/static/assets/authCallback-vY5eu2lI.js +1 -0
  82. solace_agent_mesh/client/webui/frontend/static/assets/client-BeBkzgWW.js +25 -0
  83. solace_agent_mesh/client/webui/frontend/static/assets/main-Bjys1KQs.js +339 -0
  84. solace_agent_mesh/client/webui/frontend/static/assets/main-C03yrETa.css +1 -0
  85. solace_agent_mesh/client/webui/frontend/static/assets/vendor-CE0AeXyK.js +395 -0
  86. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -2
  87. solace_agent_mesh/client/webui/frontend/static/index.html +4 -3
  88. solace_agent_mesh/common/a2a/__init__.py +213 -0
  89. solace_agent_mesh/common/a2a/a2a_llm.txt +182 -0
  90. solace_agent_mesh/common/a2a/artifact.py +328 -0
  91. solace_agent_mesh/common/a2a/events.py +183 -0
  92. solace_agent_mesh/common/a2a/message.py +307 -0
  93. solace_agent_mesh/common/a2a/protocol.py +513 -0
  94. solace_agent_mesh/common/a2a/task.py +127 -0
  95. solace_agent_mesh/common/a2a/translation.py +653 -0
  96. solace_agent_mesh/common/a2a/types.py +54 -0
  97. solace_agent_mesh/common/a2a_spec/a2a.json +2576 -0
  98. solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +407 -0
  99. solace_agent_mesh/common/a2a_spec/schemas/agent_progress_update.json +18 -0
  100. solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +31 -0
  101. solace_agent_mesh/common/a2a_spec/schemas/llm_invocation.json +18 -0
  102. solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +235 -0
  103. solace_agent_mesh/common/a2a_spec/schemas/tool_invocation_start.json +26 -0
  104. solace_agent_mesh/common/a2a_spec/schemas/tool_result.json +25 -0
  105. solace_agent_mesh/common/agent_registry.py +1 -1
  106. solace_agent_mesh/common/common_llm.txt +192 -70
  107. solace_agent_mesh/common/data_parts.py +99 -0
  108. solace_agent_mesh/common/middleware/middleware_llm.txt +17 -17
  109. solace_agent_mesh/common/sac/__init__.py +0 -0
  110. solace_agent_mesh/common/sac/sac_llm.txt +71 -0
  111. solace_agent_mesh/common/sac/sam_component_base.py +252 -0
  112. solace_agent_mesh/common/services/providers/providers_llm.txt +51 -84
  113. solace_agent_mesh/common/services/services_llm.txt +206 -26
  114. solace_agent_mesh/common/utils/artifact_utils.py +29 -0
  115. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +176 -80
  116. solace_agent_mesh/common/utils/embeds/resolver.py +1 -0
  117. solace_agent_mesh/common/utils/utils_llm.txt +323 -42
  118. solace_agent_mesh/config_portal/backend/common.py +2 -2
  119. solace_agent_mesh/config_portal/backend/plugin_catalog/constants.py +1 -1
  120. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-bFMKlzKf.js +98 -0
  121. solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-d845808d.js → manifest-89db7c30.js} +1 -1
  122. solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
  123. solace_agent_mesh/core_a2a/core_a2a_llm.txt +10 -8
  124. solace_agent_mesh/core_a2a/service.py +20 -44
  125. solace_agent_mesh/evaluation/message_organizer.py +35 -56
  126. solace_agent_mesh/evaluation/run.py +26 -5
  127. solace_agent_mesh/evaluation/subscriber.py +35 -10
  128. solace_agent_mesh/evaluation/summary_builder.py +27 -34
  129. solace_agent_mesh/gateway/base/app.py +27 -1
  130. solace_agent_mesh/gateway/base/base_llm.txt +177 -72
  131. solace_agent_mesh/gateway/base/component.py +294 -523
  132. solace_agent_mesh/gateway/gateway_llm.txt +299 -58
  133. solace_agent_mesh/gateway/http_sse/ARCHITECTURE_GUIDE.md +676 -0
  134. solace_agent_mesh/gateway/http_sse/alembic/env.py +85 -0
  135. solace_agent_mesh/gateway/http_sse/alembic/script.py.mako +28 -0
  136. solace_agent_mesh/gateway/http_sse/alembic/versions/b1c2d3e4f5g6_add_database_indexes.py +83 -0
  137. solace_agent_mesh/gateway/http_sse/alembic/versions/d5b3f8f2e9a0_create_initial_database.py +58 -0
  138. solace_agent_mesh/gateway/http_sse/alembic.ini +147 -0
  139. solace_agent_mesh/gateway/http_sse/api/__init__.py +11 -0
  140. solace_agent_mesh/gateway/http_sse/api/controllers/__init__.py +9 -0
  141. solace_agent_mesh/gateway/http_sse/api/controllers/session_controller.py +355 -0
  142. solace_agent_mesh/gateway/http_sse/api/controllers/task_controller.py +279 -0
  143. solace_agent_mesh/gateway/http_sse/api/controllers/user_controller.py +35 -0
  144. solace_agent_mesh/gateway/http_sse/api/dto/__init__.py +10 -0
  145. solace_agent_mesh/gateway/http_sse/api/dto/requests/__init__.py +37 -0
  146. solace_agent_mesh/gateway/http_sse/api/dto/requests/session_requests.py +49 -0
  147. solace_agent_mesh/gateway/http_sse/api/dto/requests/task_requests.py +66 -0
  148. solace_agent_mesh/gateway/http_sse/api/dto/responses/__init__.py +43 -0
  149. solace_agent_mesh/gateway/http_sse/api/dto/responses/session_responses.py +68 -0
  150. solace_agent_mesh/gateway/http_sse/api/dto/responses/task_responses.py +74 -0
  151. solace_agent_mesh/gateway/http_sse/app.py +31 -1
  152. solace_agent_mesh/gateway/http_sse/application/__init__.py +3 -0
  153. solace_agent_mesh/gateway/http_sse/application/services/__init__.py +3 -0
  154. solace_agent_mesh/gateway/http_sse/application/services/session_service.py +135 -0
  155. solace_agent_mesh/gateway/http_sse/component.py +371 -236
  156. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +29 -29
  157. solace_agent_mesh/gateway/http_sse/dependencies.py +142 -39
  158. solace_agent_mesh/gateway/http_sse/domain/entities/__init__.py +3 -0
  159. solace_agent_mesh/gateway/http_sse/domain/entities/session.py +90 -0
  160. solace_agent_mesh/gateway/http_sse/domain/repositories/__init__.py +3 -0
  161. solace_agent_mesh/gateway/http_sse/domain/repositories/session_repository.py +54 -0
  162. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +272 -36
  163. solace_agent_mesh/gateway/http_sse/infrastructure/__init__.py +4 -0
  164. solace_agent_mesh/gateway/http_sse/infrastructure/dependency_injection/__init__.py +3 -0
  165. solace_agent_mesh/gateway/http_sse/infrastructure/dependency_injection/container.py +123 -0
  166. solace_agent_mesh/gateway/http_sse/infrastructure/persistence/__init__.py +4 -0
  167. solace_agent_mesh/gateway/http_sse/infrastructure/persistence/database_persistence_service.py +16 -0
  168. solace_agent_mesh/gateway/http_sse/infrastructure/persistence/database_service.py +119 -0
  169. solace_agent_mesh/gateway/http_sse/infrastructure/persistence/models.py +31 -0
  170. solace_agent_mesh/gateway/http_sse/infrastructure/persistence_service.py +12 -0
  171. solace_agent_mesh/gateway/http_sse/infrastructure/repositories/__init__.py +3 -0
  172. solace_agent_mesh/gateway/http_sse/infrastructure/repositories/session_repository.py +174 -0
  173. solace_agent_mesh/gateway/http_sse/main.py +293 -91
  174. solace_agent_mesh/gateway/http_sse/routers/agents.py +1 -1
  175. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +137 -56
  176. solace_agent_mesh/gateway/http_sse/routers/config.py +3 -1
  177. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +231 -5
  178. solace_agent_mesh/gateway/http_sse/routers/tasks.py +199 -171
  179. solace_agent_mesh/gateway/http_sse/routers/visualization.py +7 -7
  180. solace_agent_mesh/gateway/http_sse/services/agent_service.py +1 -1
  181. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +89 -135
  182. solace_agent_mesh/gateway/http_sse/services/task_service.py +2 -5
  183. solace_agent_mesh/gateway/http_sse/session_manager.py +64 -30
  184. solace_agent_mesh/gateway/http_sse/shared/__init__.py +9 -0
  185. solace_agent_mesh/gateway/http_sse/shared/auth_utils.py +29 -0
  186. solace_agent_mesh/gateway/http_sse/shared/enums.py +45 -0
  187. solace_agent_mesh/gateway/http_sse/shared/types.py +45 -0
  188. solace_agent_mesh/solace_agent_mesh_llm.txt +362 -0
  189. solace_agent_mesh/templates/gateway_component_template.py +149 -98
  190. solace_agent_mesh/templates/shared_config.yaml +4 -5
  191. solace_agent_mesh/templates/webui.yaml +8 -10
  192. {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/METADATA +9 -6
  193. {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/RECORD +197 -141
  194. solace_agent_mesh/assets/docs/assets/js/f284c35a.731836ad.js +0 -1
  195. solace_agent_mesh/assets/docs/assets/js/main.3d0e7879.js +0 -2
  196. solace_agent_mesh/assets/docs/assets/js/runtime~main.05d19492.js +0 -1
  197. solace_agent_mesh/assets/docs/lunr-index-1757091012487.json +0 -1
  198. solace_agent_mesh/assets/docs/search-doc-1757091012487.json +0 -1
  199. solace_agent_mesh/client/webui/frontend/static/assets/authCallback-BmF2l6vg.js +0 -1
  200. solace_agent_mesh/client/webui/frontend/static/assets/client-D881Dttc.js +0 -49
  201. solace_agent_mesh/client/webui/frontend/static/assets/main-D0FnP_W4.css +0 -1
  202. solace_agent_mesh/client/webui/frontend/static/assets/main-Do32sFPX.js +0 -708
  203. solace_agent_mesh/common/a2a_protocol.py +0 -564
  204. solace_agent_mesh/common/client/__init__.py +0 -4
  205. solace_agent_mesh/common/client/card_resolver.py +0 -21
  206. solace_agent_mesh/common/client/client.py +0 -85
  207. solace_agent_mesh/common/client/client_llm.txt +0 -133
  208. solace_agent_mesh/common/server/__init__.py +0 -4
  209. solace_agent_mesh/common/server/server.py +0 -122
  210. solace_agent_mesh/common/server/server_llm.txt +0 -169
  211. solace_agent_mesh/common/server/task_manager.py +0 -291
  212. solace_agent_mesh/common/server/utils.py +0 -28
  213. solace_agent_mesh/common/types.py +0 -411
  214. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-Bym6YkMd.js +0 -98
  215. solace_agent_mesh/gateway/http_sse/routers/sessions.py +0 -80
  216. solace_agent_mesh/gateway/http_sse/routers/users.py +0 -59
  217. /solace_agent_mesh/assets/docs/assets/js/{main.3d0e7879.js.LICENSE.txt → main.08d30374.js.LICENSE.txt} +0 -0
  218. {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/WHEEL +0 -0
  219. {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/entry_points.txt +0 -0
  220. {solace_agent_mesh-1.0.9.dist-info → solace_agent_mesh-1.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
1
- Here is the comprehensive developer guide for the `http_sse` directory.
1
+ # DEVELOPER GUIDE for the http_sse directory
2
2
 
3
3
  ## Quick Summary
4
4
  The `http_sse` directory implements a complete HTTP/SSE (Server-Sent Events) gateway for the A2A (Agent-to-Agent) system. Its primary purpose is to serve a web-based user interface and act as a bridge between standard web protocols (HTTP, WebSockets/SSE) and the backend A2A messaging fabric.
@@ -6,26 +6,26 @@ The `http_sse` directory implements a complete HTTP/SSE (Server-Sent Events) gat
6
6
  The architecture is centered around the `WebUIBackendComponent`, a custom Solace AI Connector (SAC) component that hosts an embedded FastAPI web server. This component manages shared state and resources, such as the `SSEManager` for real-time updates, the `SessionManager` for user sessions, and the `AgentRegistry` for discovering available agents.
7
7
 
8
8
  Subdirectories organize the functionality:
9
- - `routers/` defines the REST API endpoints (e.g., `/tasks`, `/agents`).
10
- - `services/` contains the business logic that the API endpoints call.
11
- - `dependencies.py` uses FastAPI's dependency injection system to provide the routers and services with safe access to the shared resources managed by the main component.
12
- - `components/` contains specialized SAC components, for example, to forward A2A messages for real-time visualization.
9
+ - `routers/` defines the REST API endpoints (e.g., `/tasks`, `/agents`).
10
+ - `services/` contains the business logic that the API endpoints call.
11
+ - `dependencies.py` uses FastAPI's dependency injection system to provide the routers and services with safe access to the shared resources managed by the main component.
12
+ - `components/` contains specialized SAC components, for example, to forward A2A messages for real-time visualization.
13
13
 
14
14
  This design creates a clean separation of concerns, where the web layer (FastAPI) is decoupled from the core messaging and state management layer (SAC Component).
15
15
 
16
16
  ## Files and Subdirectories Overview
17
17
  - **Direct files:**
18
- - `__init__.py`: Standard Python package initializer.
19
- - `app.py`: Defines the main SAC `WebUIBackendApp`, which specifies configuration and launches the component.
20
- - `component.py`: The core SAC component that hosts the FastAPI server and manages all shared resources and A2A logic.
21
- - `dependencies.py`: Provides FastAPI dependency injectors for accessing shared resources like services and managers.
22
- - `main.py`: The main FastAPI application instance, including middleware, router mounting, and exception handling.
23
- - `session_manager.py`: Manages web user sessions and maps them to unique A2A client and session IDs.
24
- - `sse_manager.py`: Manages Server-Sent Event (SSE) connections for streaming real-time updates to clients.
18
+ - `__init__.py`: Standard Python package initializer.
19
+ - `app.py`: Defines the main SAC `WebUIBackendApp`, which specifies configuration and launches the component.
20
+ - `component.py`: The core SAC component that hosts the FastAPI server and manages all shared resources and A2A logic.
21
+ - `dependencies.py`: Provides FastAPI dependency injectors for accessing shared resources like services and managers.
22
+ - `main.py`: The main FastAPI application instance, including middleware, router mounting, and exception handling.
23
+ - `session_manager.py`: Manages web user sessions and maps them to unique A2A client and session IDs.
24
+ - `sse_manager.py`: Manages Server-Sent Event (SSE) connections for streaming real-time updates to clients.
25
25
  - **Subdirectories:**
26
- - `components/`: Contains specialized SAC components, such as for forwarding messages to the visualization system.
27
- - `routers/`: Defines the FastAPI `APIRouter` modules for all REST API endpoints.
28
- - `services/`: Encapsulates business logic for agents, tasks, and other domain-specific operations.
26
+ - `components/`: Contains specialized SAC components, such as for forwarding messages to the visualization system.
27
+ - `routers/`: Defines the FastAPI `APIRouter` modules for all REST API endpoints.
28
+ - `services/`: Encapsulates business logic for agents, tasks, and other domain-specific operations.
29
29
 
30
30
  ## Developer API Reference
31
31
 
@@ -33,31 +33,267 @@ This design creates a clean separation of concerns, where the web layer (FastAPI
33
33
 
34
34
  #### app.py
35
35
  **Purpose:** This file defines the `WebUIBackendApp`, a custom SAC (Solace AI Connector) App class. It is responsible for defining the configuration schema for the entire HTTP/SSE gateway and programmatically creating the `WebUIBackendComponent`.
36
- **Import:** `from gateway.http_sse.app import WebUIBackendApp`
36
+ **Import:** `from solace_agent_mesh.gateway.http_sse.app import WebUIBackendApp`
37
37
 
38
38
  **Classes/Functions/Constants:**
39
- - **`WebUIBackendApp(BaseGatewayApp)`**: The main application class. It extends `BaseGatewayApp` and adds a list of WebUI-specific configuration parameters to the application schema.
40
- - **`SPECIFIC_APP_SCHEMA_PARAMS: List[Dict[str, Any]]`**: A constant list defining the configuration parameters specific to the HTTP/SSE gateway, such as `session_secret_key`, `fastapi_host`, `fastapi_port`, and various frontend-related settings.
39
+ - **`WebUIBackendApp(BaseGatewayApp)`**: The main application class. It extends `BaseGatewayApp` and adds a list of WebUI-specific configuration parameters to the application schema.
40
+ - **`SPECIFIC_APP_SCHEMA_PARAMS: List[Dict[str, Any]]`**: A constant list defining the configuration parameters specific to the HTTP/SSE gateway, such as `session_secret_key`, `fastapi_host`, `fastapi_port`, and various frontend-related settings.
41
41
 
42
42
  #### component.py
43
43
  **Purpose:** This is the core component of the gateway. It hosts the FastAPI server, manages all shared state (like the SSE and Session managers), handles the lifecycle of the web server, and implements the logic for translating between external HTTP requests and internal A2A messages.
44
- **Import:** `from gateway.http_sse.component import WebUIBackendComponent`
44
+ **Import:** `from solace_agent_mesh.gateway.http_sse.component import WebUIBackendComponent`
45
45
 
46
46
  **Classes/Functions/Constants:**
47
- - **`WebUIBackendComponent(BaseGatewayComponent)`**: The main component class. Developers will primarily interact with its instances via the dependency injection system.
48
- - **Public Accessor Methods (for Dependencies):**
49
- - `get_sse_manager() -> SSEManager`: Returns the shared `SSEManager` instance.
50
- - `get_session_manager() -> SessionManager`: Returns the shared `SessionManager` instance.
51
- - `get_agent_registry() -> AgentRegistry`: Returns the shared `AgentRegistry` instance.
52
- - `get_core_a2a_service() -> CoreA2AService`: Returns the core service for creating A2A messages.
53
- - `get_shared_artifact_service() -> Optional[BaseArtifactService]`: Returns the service for artifact storage.
54
- - `get_namespace() -> str`: Returns the configured namespace.
55
- - `get_gateway_id() -> str`: Returns the unique ID of this gateway.
56
- - **Core Logic Methods:**
57
- - `publish_a2a(topic: str, payload: Dict, user_properties: Optional[Dict] = None)`: Publishes a message onto the A2A messaging fabric. This is the primary method for sending data to agents.
58
- - **Gateway-Development-Kit (GDK) Hooks:** These methods implement the `BaseGatewayComponent` abstract interface.
59
- - `_start_listener()`: Starts the FastAPI/Uvicorn server.
60
- - `_stop_listener()`: Stops the FastAPI/Uvicorn server.
61
- - `_translate_external_input(...)`: Translates an incoming HTTP request (e.g., form data with files) into a structured A2A message (`List[A2APart]`).
62
- - `_send_update_to_external(...)`: Sends an intermediate status update from an agent back to the client via SSE.
63
- -
47
+ - **`WebUIBackendComponent(BaseGatewayComponent)`**: The main component class. Developers will primarily interact with its instances via the dependency injection system.
48
+ - **Public Accessor Methods (for Dependencies):**
49
+ - `get_sse_manager() -> SSEManager`: Returns the shared `SSEManager` instance.
50
+ - `get_session_manager() -> SessionManager`: Returns the shared `SessionManager` instance.
51
+ - `get_agent_registry() -> AgentRegistry`: Returns the shared `AgentRegistry` instance.
52
+ - `get_core_a2a_service() -> CoreA2AService`: Returns the core service for creating A2A messages.
53
+ - `get_shared_artifact_service() -> Optional[BaseArtifactService]`: Returns the service for artifact storage.
54
+ - `get_namespace() -> str`: Returns the configured A2A namespace.
55
+ - `get_gateway_id() -> str`: Returns the unique ID of this gateway.
56
+ - **Core Logic Methods:**
57
+ - `publish_a2a(topic: str, payload: Dict, user_properties: Optional[Dict] = None)`: Publishes a message onto the A2A messaging fabric. This is the primary method for sending data to agents.
58
+ - **Gateway-Development-Kit (GDK) Hooks:** These methods implement the `BaseGatewayComponent` abstract interface.
59
+ - `_start_listener()`: Starts the FastAPI/Uvicorn server.
60
+ - `_stop_listener()`: Stops the FastAPI/Uvicorn server.
61
+ - `_translate_external_input(...)`: Translates an incoming HTTP request (e.g., form data with files) into a structured A2A message (`List[ContentPart]`).
62
+ - `_send_update_to_external(...)`: Sends an intermediate status update from an agent back to the client via SSE.
63
+ - `_send_final_response_to_external(...)`: Sends the final A2A Task result to the client via SSE.
64
+ - `_send_error_to_external(...)`: Sends an error notification to the client via SSE.
65
+
66
+ #### dependencies.py
67
+ **Purpose:** Defines FastAPI dependency injectors to access shared resources managed by the WebUIBackendComponent.
68
+ **Import:** `from solace_agent_mesh.gateway.http_sse.dependencies import *`
69
+
70
+ **Functions:**
71
+ - `get_sac_component() -> WebUIBackendComponent`: Returns the main component instance.
72
+ - `get_agent_registry() -> AgentRegistry`: Returns the shared agent registry.
73
+ - `get_sse_manager() -> SSEManager`: Returns the SSE manager for real-time updates.
74
+ - `get_session_manager() -> SessionManager`: Returns the session manager.
75
+ - `get_user_id(request: Request) -> str`: Returns the current user's identity.
76
+ - `get_publish_a2a_func() -> PublishFunc`: Returns the function for publishing A2A messages.
77
+ - `get_core_a2a_service() -> CoreA2AService`: Returns the core A2A service.
78
+ - `get_shared_artifact_service() -> Optional[BaseArtifactService]`: Returns the artifact service.
79
+
80
+ #### main.py
81
+ **Purpose:** Defines the FastAPI application instance, mounts routers, and configures middleware.
82
+ **Import:** `from solace_agent_mesh.gateway.http_sse.main import app, setup_dependencies`
83
+
84
+ **Classes/Functions/Constants:**
85
+ - **`app: FastAPI`**: The main FastAPI application instance.
86
+ - **`setup_dependencies(component: WebUIBackendComponent)`**: Configures middleware, routers, and dependency injection based on the component instance.
87
+
88
+ #### session_manager.py
89
+ **Purpose:** Manages web user sessions and mapping to A2A Client IDs.
90
+ **Import:** `from solace_agent_mesh.gateway.http_sse.session_manager import SessionManager`
91
+
92
+ **Classes/Functions/Constants:**
93
+ - **`SessionManager(secret_key: str, app_config: Dict[str, Any])`**: Manages user sessions and A2A identity mapping.
94
+ - `get_a2a_client_id(request: Request) -> str`: Returns the A2A client ID for the current request.
95
+ - `start_new_a2a_session(request: Request) -> str`: Creates a new A2A session ID.
96
+ - `ensure_a2a_session(request: Request) -> str`: Ensures a session ID exists, creating one if necessary.
97
+ - `store_auth_tokens(request: Request, access_token: str, refresh_token: Optional[str])`: Stores authentication tokens.
98
+ - `get_access_token(request: Request) -> Optional[str]`: Retrieves stored access token.
99
+
100
+ #### sse_manager.py
101
+ **Purpose:** Manages Server-Sent Event (SSE) connections for streaming task updates.
102
+ **Import:** `from solace_agent_mesh.gateway.http_sse.sse_manager import SSEManager`
103
+
104
+ **Classes/Functions/Constants:**
105
+ - **`SSEManager(max_queue_size: int = 200)`**: Manages active SSE connections and distributes events.
106
+ - `create_sse_connection(task_id: str) -> asyncio.Queue`: Creates a new SSE connection queue for a task.
107
+ - `send_event(task_id: str, event_data: Dict[str, Any], event_type: str)`: Sends an event to all connections for a task.
108
+ - `close_all_for_task(task_id: str)`: Closes all SSE connections for a specific task.
109
+ - `close_all()`: Closes all active SSE connections.
110
+
111
+ ### Subdirectory APIs
112
+
113
+ #### components/
114
+ **Purpose:** Contains specialized SAC components for message forwarding and visualization
115
+ **Key Exports:** `VisualizationForwarderComponent`
116
+ **Import Examples:**
117
+ ```python
118
+ from solace_agent_mesh.gateway.http_sse.components import VisualizationForwarderComponent
119
+ ```
120
+
121
+ #### routers/
122
+ **Purpose:** Defines FastAPI APIRouter modules for all REST API endpoints
123
+ **Key Exports:** Router instances for agents, tasks, SSE, artifacts, auth, config, sessions, people, users, visualization
124
+ **Import Examples:**
125
+ ```python
126
+ from solace_agent_mesh.gateway.http_sse.routers import agents, tasks, sse, artifacts
127
+ from solace_agent_mesh.gateway.http_sse.routers.tasks import CancelTaskApiPayload
128
+ ```
129
+
130
+ #### services/
131
+ **Purpose:** Encapsulates business logic for domain-specific operations
132
+ **Key Exports:** `AgentService`, `TaskService`, `PeopleService`
133
+ **Import Examples:**
134
+ ```python
135
+ from solace_agent_mesh.gateway.http_sse.services.agent_service import AgentService
136
+ from solace_agent_mesh.gateway.http_sse.services.task_service import TaskService
137
+ from solace_agent_mesh.gateway.http_sse.services.people_service import PeopleService
138
+ ```
139
+
140
+ ## Complete Usage Guide
141
+
142
+ ### 1. Setting Up the Gateway Application
143
+
144
+ ```python
145
+ from solace_agent_mesh.gateway.http_sse.app import WebUIBackendApp
146
+
147
+ # Create the gateway app with configuration
148
+ app_config = {
149
+ "name": "my-webui-gateway",
150
+ "session_secret_key": "your-secret-key-here",
151
+ "fastapi_host": "0.0.0.0",
152
+ "fastapi_port": 8000,
153
+ "namespace": "/my-namespace",
154
+ "gateway_id": "webui-gateway-01",
155
+ "cors_allowed_origins": ["http://localhost:3000"],
156
+ "frontend_welcome_message": "Welcome to my A2A system!",
157
+ "frontend_bot_name": "My Assistant",
158
+ # ... other configuration parameters
159
+ }
160
+
161
+ # Initialize the app
162
+ webui_app = WebUIBackendApp(app_info=app_config)
163
+
164
+ # Run the app (this starts the FastAPI server)
165
+ webui_app.run()
166
+ ```
167
+
168
+ ### 2. Using Dependencies in Custom Routers
169
+
170
+ ```python
171
+ from fastapi import APIRouter, Depends
172
+ from solace_agent_mesh.gateway.http_sse.dependencies import (
173
+ get_agent_registry,
174
+ get_user_id,
175
+ get_publish_a2a_func,
176
+ get_core_a2a_service
177
+ )
178
+ from solace_agent_mesh.common.agent_registry import AgentRegistry
179
+
180
+ router = APIRouter()
181
+
182
+ @router.get("/my-custom-endpoint")
183
+ async def my_custom_endpoint(
184
+ user_id: str = Depends(get_user_id),
185
+ agent_registry: AgentRegistry = Depends(get_agent_registry),
186
+ publish_func = Depends(get_publish_a2a_func)
187
+ ):
188
+ # Access discovered agents
189
+ agents = agent_registry.get_all_agents()
190
+
191
+ # Publish a message to the A2A fabric
192
+ publish_func(
193
+ topic=f"/my-namespace/a2a/v1/agent/request/some-agent",
194
+ payload={"method": "custom/request", "params": {"user": user_id}},
195
+ user_properties={"clientId": user_id}
196
+ )
197
+
198
+ return {"agents_count": len(agents), "user_id": user_id}
199
+ ```
200
+
201
+ ### 3. Managing SSE Connections
202
+
203
+ ```python
204
+ from fastapi import APIRouter, Depends
205
+ from fastapi.responses import StreamingResponse
206
+ from solace_agent_mesh.gateway.http_sse.dependencies import get_sse_manager
207
+ from solace_agent_mesh.gateway.http_sse.sse_manager import SSEManager
208
+ import asyncio
209
+ import json
210
+
211
+ router = APIRouter()
212
+
213
+ @router.get("/my-sse-endpoint/{task_id}")
214
+ async def my_sse_endpoint(
215
+ task_id: str,
216
+ sse_manager: SSEManager = Depends(get_sse_manager)
217
+ ):
218
+ # Create SSE connection for the task
219
+ connection_queue = await sse_manager.create_sse_connection(task_id)
220
+
221
+ async def event_generator():
222
+ try:
223
+ while True:
224
+ # Wait for events from the queue
225
+ event = await connection_queue.get()
226
+ if event is None: # Close signal
227
+ break
228
+
229
+ # Format as SSE
230
+ yield f"event: {event['event']}\n"
231
+ yield f"data: {event['data']}\n\n"
232
+
233
+ except asyncio.CancelledError:
234
+ pass
235
+ finally:
236
+ # Clean up connection
237
+ await sse_manager.remove_sse_connection(task_id, connection_queue)
238
+
239
+ return StreamingResponse(
240
+ event_generator(),
241
+ media_type="text/event-stream",
242
+ headers={
243
+ "Cache-Control": "no-cache",
244
+ "Connection": "keep-alive",
245
+ }
246
+ )
247
+
248
+ # Send events to SSE connections
249
+ async def send_custom_event(sse_manager: SSEManager, task_id: str):
250
+ await sse_manager.send_event(
251
+ task_id=task_id,
252
+ event_data={"message": "Custom event", "timestamp": "2024-01-01T00:00:00Z"},
253
+ event_type="custom_event"
254
+ )
255
+ ```
256
+
257
+ ### 4. Working with Sessions and User Identity
258
+
259
+ ```python
260
+ from fastapi import APIRouter, Depends, Request
261
+ from solace_agent_mesh.gateway.http_sse.dependencies import (
262
+ get_session_manager,
263
+ get_user_id,
264
+ ensure_session_id
265
+ )
266
+ from solace_agent_mesh.gateway.http_sse.session_manager import SessionManager
267
+
268
+ router = APIRouter()
269
+
270
+ @router.post("/start-conversation")
271
+ async def start_conversation(
272
+ request: Request,
273
+ user_id: str = Depends(get_user_id),
274
+ session_id: str = Depends(ensure_session_id),
275
+ session_manager: SessionManager = Depends(get_session_manager)
276
+ ):
277
+ # Start a new A2A session for this conversation
278
+ new_session_id = session_manager.start_new_a2a_session(request)
279
+
280
+ return {
281
+ "user_id": user_id,
282
+ "old_session_id": session_id,
283
+ "new_session_id": new_session_id,
284
+ "message": "New conversation started"
285
+ }
286
+ ```
287
+
288
+ ### 5. Using Services for Business Logic
289
+
290
+ ```python
291
+ from fastapi import APIRouter, Depends
292
+ from solace_agent_mesh.gateway.http_sse.dependencies import (
293
+ get_agent_service,
294
+ get_task_service,
295
+ get_people_service
296
+ )
297
+ from solace_agent_mesh.gateway.http_sse.services.agent_service import AgentService
298
+
299
+ # content_hash: 765fb33c6a30298c67ac7c1525df5787791b2b37e0d69b046e405aec85287feb
@@ -0,0 +1,4 @@
1
+ from .persistence.database_service import DatabaseService
2
+ from .repositories.session_repository import SessionRepository, MessageRepository
3
+
4
+ __all__ = ["DatabaseService", "SessionRepository", "MessageRepository"]
@@ -0,0 +1,3 @@
1
+ from .container import ApplicationContainer, get_container, initialize_container
2
+
3
+ __all__ = ["ApplicationContainer", "initialize_container", "get_container"]
@@ -0,0 +1,123 @@
1
+ from collections.abc import Callable
2
+ from typing import Any, TypeVar
3
+
4
+ from ...application.services.session_service import SessionService
5
+ from ...domain.repositories.session_repository import (
6
+ IMessageRepository,
7
+ ISessionRepository,
8
+ )
9
+ from ...infrastructure.persistence import database_service as db_service_module
10
+ from ...infrastructure.persistence.database_service import DatabaseService
11
+ from ...infrastructure.repositories.session_repository import (
12
+ MessageRepository,
13
+ SessionRepository,
14
+ )
15
+
16
+ T = TypeVar("T")
17
+
18
+
19
+ class DIContainer:
20
+ """Dependency injection container."""
21
+
22
+ def __init__(self):
23
+ self._services: dict[str, Any] = {}
24
+ self._factories: dict[str, Callable] = {}
25
+ self._singletons: dict[str, Any] = {}
26
+
27
+ def register_singleton(self, service_type: type, instance: Any) -> None:
28
+ self._singletons[service_type.__name__] = instance
29
+
30
+ def register_factory(self, service_type: type, factory: Callable) -> None:
31
+ self._factories[service_type.__name__] = factory
32
+
33
+ def register_transient(self, service_type: type, implementation: type) -> None:
34
+ """Register a transient service (new instance each time)."""
35
+ self._services[service_type.__name__] = implementation
36
+
37
+ def get(self, service_type: type) -> Any:
38
+ """Get an instance of the requested service."""
39
+ service_name = service_type.__name__
40
+
41
+ # Check singletons first
42
+ if service_name in self._singletons:
43
+ return self._singletons[service_name]
44
+
45
+ # Check factories
46
+ if service_name in self._factories:
47
+ return self._factories[service_name]()
48
+
49
+ # Check transient services
50
+ if service_name in self._services:
51
+ implementation = self._services[service_name]
52
+ return self._create_instance(implementation)
53
+
54
+ raise ValueError(f"Service {service_name} is not registered")
55
+
56
+ def _create_instance(self, implementation: type) -> Any:
57
+ """Create an instance with dependency injection."""
58
+ # This is a simplified implementation
59
+ # In a production system, you'd use a more sophisticated approach
60
+ # like inspecting constructor parameters and resolving them automatically
61
+ return implementation()
62
+
63
+
64
+ class ApplicationContainer:
65
+ """Application-specific dependency injection container."""
66
+
67
+ def __init__(self, database_url: str | None = None):
68
+ self.container = DIContainer()
69
+ self.database_url = database_url
70
+ self.has_database = database_url is not None
71
+ self._setup_dependencies()
72
+
73
+ def _setup_dependencies(self) -> None:
74
+ if self.has_database:
75
+ database_service = DatabaseService(self.database_url)
76
+ self.container.register_singleton(DatabaseService, database_service)
77
+ db_service_module.database_service = database_service
78
+
79
+ session_repository = SessionRepository(database_service)
80
+ message_repository = MessageRepository(database_service)
81
+
82
+ self.container.register_singleton(ISessionRepository, session_repository)
83
+ self.container.register_singleton(IMessageRepository, message_repository)
84
+
85
+ def session_service_factory():
86
+ return SessionService(session_repository, message_repository)
87
+
88
+ self.container.register_factory(SessionService, session_service_factory)
89
+
90
+ def get_database_service(self) -> DatabaseService | None:
91
+ if not self.has_database:
92
+ return None
93
+ return self.container.get(DatabaseService)
94
+
95
+ def get_session_service(self) -> SessionService | None:
96
+ if not self.has_database:
97
+ return None
98
+ return self.container.get(SessionService)
99
+
100
+
101
+ # Global container instance
102
+ _container: ApplicationContainer | None = None
103
+
104
+
105
+ def initialize_container(database_url: str | None = None) -> ApplicationContainer:
106
+ global _container
107
+ _container = ApplicationContainer(database_url)
108
+
109
+ # Only create tables if database is available
110
+ if _container.has_database:
111
+ database_service = _container.get_database_service()
112
+ if database_service:
113
+ database_service.create_tables()
114
+
115
+ return _container
116
+
117
+
118
+ def get_container() -> ApplicationContainer:
119
+ if _container is None:
120
+ raise RuntimeError(
121
+ "Container not initialized. Call initialize_container() first."
122
+ )
123
+ return _container
@@ -0,0 +1,4 @@
1
+ from .database_service import DatabaseService
2
+ from .models import Base, SessionModel, MessageModel
3
+
4
+ __all__ = ["DatabaseService", "Base", "SessionModel", "MessageModel"]
@@ -0,0 +1,16 @@
1
+ from sqlalchemy.orm import sessionmaker
2
+
3
+ from .database_service import DatabaseService
4
+
5
+
6
+ class DatabasePersistenceService:
7
+ def __init__(self, db_url: str):
8
+ self.db_service = DatabaseService(db_url)
9
+ self._session_factory = sessionmaker(bind=self.db_service.engine)
10
+
11
+ def Session(self):
12
+ return self._session_factory()
13
+
14
+ @property
15
+ def engine(self):
16
+ return self.db_service.engine
@@ -0,0 +1,119 @@
1
+ import logging
2
+ from collections.abc import Generator
3
+ from contextlib import contextmanager
4
+
5
+ from sqlalchemy import create_engine, event
6
+ from sqlalchemy.orm import Session, sessionmaker
7
+
8
+ from .models import Base
9
+
10
+
11
+ def get_database_type(database_url: str) -> str:
12
+ """Get the database type from a database URL."""
13
+ if database_url.startswith("sqlite"):
14
+ return "sqlite"
15
+ elif database_url.startswith("postgresql"):
16
+ return "postgresql"
17
+ else:
18
+ return "unknown"
19
+
20
+
21
+ class DatabaseService:
22
+ def __init__(self, database_url: str):
23
+ self.database_url = database_url
24
+ self.logger = logging.getLogger(__name__)
25
+
26
+ if database_url.startswith("sqlite"):
27
+ self._setup_sqlite_engine(database_url)
28
+ elif database_url.startswith("postgresql"):
29
+ self._setup_postgresql_engine(database_url)
30
+ else:
31
+ # Fallback for other databases
32
+ self._setup_generic_engine(database_url)
33
+
34
+ self.SessionLocal = sessionmaker(
35
+ autocommit=False, autoflush=False, bind=self.engine
36
+ )
37
+
38
+ def _setup_sqlite_engine(self, database_url: str):
39
+ """Configure SQLite-specific engine settings."""
40
+ self.engine = create_engine(
41
+ database_url,
42
+ echo=False,
43
+ connect_args={
44
+ "check_same_thread": False,
45
+ },
46
+ )
47
+
48
+ @event.listens_for(self.engine, "connect")
49
+ def set_sqlite_pragma(dbapi_connection, connection_record):
50
+ cursor = dbapi_connection.cursor()
51
+ cursor.execute("PRAGMA foreign_keys=ON")
52
+ cursor.close()
53
+
54
+ def _setup_postgresql_engine(self, database_url: str):
55
+ """Configure PostgreSQL-specific engine settings."""
56
+ try:
57
+ import psycopg2
58
+ except ImportError:
59
+ raise ImportError(
60
+ "PostgreSQL support requires psycopg2. Install with: "
61
+ "pip install 'solace-agent-mesh[postgresql]'"
62
+ )
63
+
64
+ self.engine = create_engine(
65
+ database_url,
66
+ pool_size=10,
67
+ max_overflow=20,
68
+ pool_timeout=30,
69
+ pool_recycle=3600,
70
+ pool_pre_ping=True,
71
+ echo=False,
72
+ )
73
+
74
+ def _setup_generic_engine(self, database_url: str):
75
+ """Configure generic database engine settings."""
76
+ self.engine = create_engine(
77
+ database_url,
78
+ pool_size=10,
79
+ max_overflow=20,
80
+ pool_timeout=30,
81
+ pool_recycle=3600,
82
+ pool_pre_ping=True,
83
+ echo=False,
84
+ )
85
+
86
+ def create_tables(self):
87
+ Base.metadata.create_all(bind=self.engine)
88
+
89
+ @contextmanager
90
+ def session_scope(self) -> Generator[Session, None, None]:
91
+ session = self.SessionLocal()
92
+ try:
93
+ yield session
94
+ session.commit()
95
+ except Exception as e:
96
+ session.rollback()
97
+ self.logger.error(f"Database transaction failed: {e}")
98
+ raise
99
+ finally:
100
+ session.close()
101
+
102
+ @contextmanager
103
+ def read_only_session(self) -> Generator[Session, None, None]:
104
+ session = self.SessionLocal()
105
+ try:
106
+ yield session
107
+ except Exception as e:
108
+ session.rollback()
109
+ self.logger.error(f"Database read operation failed: {e}")
110
+ raise
111
+ finally:
112
+ session.close()
113
+
114
+
115
+ database_service: DatabaseService = None
116
+
117
+
118
+ def get_database_service() -> DatabaseService:
119
+ return database_service
@@ -0,0 +1,31 @@
1
+ from sqlalchemy import Column, DateTime, ForeignKey, String, Text
2
+ from sqlalchemy.orm import declarative_base, relationship
3
+ from sqlalchemy.sql import func
4
+
5
+ Base = declarative_base()
6
+
7
+
8
+ class SessionModel(Base):
9
+ __tablename__ = "sessions"
10
+ id = Column(String, primary_key=True)
11
+ name = Column(String, nullable=True)
12
+ user_id = Column(String, nullable=False)
13
+ agent_id = Column(String, nullable=True)
14
+ created_at = Column(DateTime, default=func.now())
15
+ updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
16
+ messages = relationship(
17
+ "MessageModel", back_populates="session", cascade="all, delete-orphan"
18
+ )
19
+
20
+
21
+ class MessageModel(Base):
22
+ __tablename__ = "chat_messages"
23
+ id = Column(String, primary_key=True)
24
+ session_id = Column(
25
+ String, ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False
26
+ )
27
+ message = Column(Text, nullable=False)
28
+ created_at = Column(DateTime, default=func.now())
29
+ sender_type = Column(String(50))
30
+ sender_name = Column(String(255))
31
+ session = relationship("SessionModel", back_populates="messages")
@@ -0,0 +1,12 @@
1
+ from .dependency_injection.container import ApplicationContainer
2
+ from .persistence.database_service import DatabaseService
3
+
4
+
5
+ class PersistenceService:
6
+ def __init__(self, database_url: str):
7
+ self.db_service = DatabaseService(database_url)
8
+ self.container = ApplicationContainer(database_url)
9
+
10
+ @property
11
+ def engine(self):
12
+ return self.db_service.engine
@@ -0,0 +1,3 @@
1
+ from .session_repository import SessionRepository, MessageRepository
2
+
3
+ __all__ = ["SessionRepository", "MessageRepository"]