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,179 +1,133 @@
1
- Here is the developer guide for the `services` directory.
1
+ # DEVELOPER GUIDE: services
2
2
 
3
3
  ## Quick Summary
4
- The `services` directory contains the business logic layer for the HTTP SSE Gateway. It encapsulates core functionalities by providing high-level services for agent management, user identity searches, and A2A (Agent-to-Agent) task operations. These services abstract the complexities of interacting with the agent registry, external identity providers, and the underlying A2A messaging protocol.
4
+ The `services` directory contains the business logic layer for the HTTP SSE Gateway. It provides high-level services for agent management (discovering and retrieving A2A agents), user identity operations (searching for users), and task management (cancelling A2A tasks). These services abstract the complexities of interacting with agent registries, identity providers, and A2A messaging protocols.
5
5
 
6
6
  ## Files Overview
7
- - `__init__.py` - Marks the directory as a Python package.
8
- - `agent_service.py` - Service for retrieving information about discovered A2A agents.
9
- - `people_service.py` - Service for searching for users via a configured identity service.
10
- - `task_service.py` - Service for handling the cancellation of tasks with A2A agents.
7
+ - `__init__.py` - Package initialization file marking the directory as a Python package
8
+ - `agent_service.py` - Service for retrieving information about discovered A2A agents from the registry
9
+ - `people_service.py` - Service for searching users via configured identity services
10
+ - `task_service.py` - Service for handling A2A task cancellation operations
11
11
 
12
12
  ## Developer API Reference
13
13
 
14
14
  ### __init__.py
15
- **Purpose:** This file marks the `services` directory as a Python package, allowing its modules to be imported.
16
- **Import:** N/A - No public interfaces.
17
-
18
- ---
15
+ **Purpose:** Marks the services directory as a Python package
16
+ **Import:** N/A - No public interfaces
19
17
 
20
18
  ### agent_service.py
21
- **Purpose:** Provides high-level methods for accessing information about discovered A2A agents from the shared `AgentRegistry`.
22
- **Import:** `from src.solace_agent_mesh.gateway.http_sse.services.agent_service import AgentService`
19
+ **Purpose:** Provides methods for accessing information about discovered A2A agents from the shared AgentRegistry
20
+ **Import:** `from solace_agent_mesh.gateway.http_sse.services.agent_service import AgentService`
23
21
 
24
22
  **Classes:**
25
- - `AgentService(agent_registry: AgentRegistry)` - A service that provides methods for accessing information about discovered A2A agents.
26
- - `get_all_agents() -> List[AgentCard]` - Retrieves all currently discovered and registered agent cards from the registry.
27
- - `get_agent_by_name(agent_name: str) -> Optional[AgentCard]` - Retrieves a specific agent card by its unique name. Returns `None` if the agent is not found.
23
+ - `AgentService(agent_registry: AgentRegistry)` - Service for accessing discovered A2A agent information
24
+ - `get_all_agents() -> List[AgentCard]` - Retrieves all currently discovered and registered agent cards
25
+ - `get_agent_by_name(agent_name: str) -> Optional[AgentCard]` - Retrieves a specific agent card by name, returns None if not found
28
26
 
29
27
  **Usage Examples:**
30
28
  ```python
31
- from typing import List, Optional
32
- from src.solace_agent_mesh.gateway.http_sse.services.agent_service import AgentService
33
- from src.solace_agent_mesh.common.agent_registry import AgentRegistry
34
- from src.solace_agent_mesh.common.types import AgentCard
35
-
36
- # In a real application, AgentRegistry would be a shared instance.
37
- # For this example, we'll create a new one and populate it.
38
- agent_registry = AgentRegistry()
39
- my_agent_card = AgentCard(name="data-analyzer", description="Analyzes data files.")
40
- agent_registry.register_agent(my_agent_card)
41
-
42
- # 1. Initialize the service with the agent registry
29
+ from solace_agent_mesh.gateway.http_sse.services.agent_service import AgentService
30
+ from solace_agent_mesh.common.agent_registry import AgentRegistry
31
+
32
+ # Initialize with shared agent registry
33
+ agent_registry = AgentRegistry() # Usually injected as shared instance
43
34
  agent_service = AgentService(agent_registry=agent_registry)
44
35
 
45
- # 2. Get all available agents
36
+ # Get all available agents
46
37
  all_agents = agent_service.get_all_agents()
47
- print(f"Found {len(all_agents)} agent(s).")
48
- for agent in all_agents:
49
- print(f"- Agent: {agent.name}, Description: {agent.description}")
50
-
51
- # 3. Get a specific agent by name
52
- found_agent = agent_service.get_agent_by_name("data-analyzer")
53
- if found_agent:
54
- print(f"\nSuccessfully retrieved agent: {found_agent.name}")
55
- else:
56
- print("\nCould not find agent 'data-analyzer'.")
38
+ print(f"Found {len(all_agents)} agents")
57
39
 
58
- # 4. Try to get a non-existent agent
59
- missing_agent = agent_service.get_agent_by_name("non-existent-agent")
60
- print(f"Result for 'non-existent-agent': {missing_agent}")
40
+ # Get specific agent by name
41
+ agent = agent_service.get_agent_by_name("data-processor")
42
+ if agent:
43
+ print(f"Found agent: {agent.name}")
44
+ else:
45
+ print("Agent not found")
61
46
  ```
62
47
 
63
- ---
64
-
65
48
  ### people_service.py
66
- **Purpose:** Acts as a layer on top of a configured `IdentityService` to provide user search functionality. If no identity service is configured, it gracefully returns empty results.
67
- **Import:** `from src.solace_agent_mesh.gateway.http_sse.services.people_service import PeopleService`
49
+ **Purpose:** Provides user search functionality via configured identity services
50
+ **Import:** `from solace_agent_mesh.gateway.http_sse.services.people_service import PeopleService`
68
51
 
69
52
  **Classes:**
70
- - `PeopleService(identity_service: Optional[BaseIdentityService])` - A service for searching and retrieving user information.
71
- - `search_for_users(query: str, limit: int = 10) -> List[Dict[str, Any]]` - Asynchronously searches for users via the identity service. Returns an empty list if the query is too short, no identity service is configured, or an error occurs.
53
+ - `PeopleService(identity_service: Optional[BaseIdentityService])` - Service for searching and retrieving user information
54
+ - `search_for_users(query: str, limit: int = 10) -> List[Dict[str, Any]]` - Asynchronously searches for users, returns empty list if no identity service configured or query too short
72
55
 
73
56
  **Usage Examples:**
74
57
  ```python
75
58
  import asyncio
76
- from typing import Any, Dict, List, Optional
77
- from src.solace_agent_mesh.gateway.http_sse.services.people_service import PeopleService
78
- from src.solace_agent_mesh.common.services.identity_service import BaseIdentityService
79
-
80
- # Define a mock identity service for the example
81
- class MockIdentityService(BaseIdentityService):
82
- async def search_users(self, query: str, limit: int) -> List[Dict[str, Any]]:
83
- print(f"MockIdentityService: Searching for '{query}' with limit {limit}")
84
- all_users = [
85
- {"id": "jdoe", "name": "John Doe", "email": "j.doe@example.com"},
86
- {"id": "jsmith", "name": "Jane Smith", "email": "j.smith@example.com"},
87
- ]
88
- return [user for user in all_users if query.lower() in user["name"].lower()][:limit]
89
-
90
- async def main():
91
- # 1. Initialize with a configured identity service
92
- identity_service = MockIdentityService()
93
- people_service = PeopleService(identity_service=identity_service)
94
-
95
- # 2. Search for users
59
+ from solace_agent_mesh.gateway.http_sse.services.people_service import PeopleService
60
+ from solace_agent_mesh.common.services.identity_service import BaseIdentityService
61
+
62
+ # Initialize with identity service
63
+ identity_service = SomeIdentityService() # Your identity service implementation
64
+ people_service = PeopleService(identity_service=identity_service)
65
+
66
+ async def search_users():
67
+ # Search for users
96
68
  users = await people_service.search_for_users("john", limit=5)
97
- print(f"Found {len(users)} user(s): {users}")
69
+ for user in users:
70
+ print(f"User: {user.get('name')} - {user.get('email')}")
98
71
 
99
- # 3. Initialize without an identity service
100
- people_service_no_id = PeopleService(identity_service=None)
101
-
102
- # 4. Search will return an empty list
103
- empty_results = await people_service_no_id.search_for_users("jane")
104
- print(f"Results with no identity service: {empty_results}")
72
+ # Initialize without identity service (graceful degradation)
73
+ people_service_no_id = PeopleService(identity_service=None)
74
+ # search_for_users will return empty list
105
75
 
106
- if __name__ == "__main__":
107
- asyncio.run(main())
76
+ asyncio.run(search_users())
108
77
  ```
109
78
 
110
- ---
111
-
112
79
  ### task_service.py
113
- **Purpose:** Handles the business logic for cancelling A2A tasks. It uses `CoreA2AService` to construct the cancellation message and a provided publisher function to send it over the messaging fabric.
114
- **Import:** `from src.solace_agent_mesh.gateway.http_sse.services.task_service import TaskService, PublishFunc`
115
-
116
- **Classes:**
117
- - `TaskService(core_a2a_service: CoreA2AService, publish_func: PublishFunc, namespace: str, gateway_id: str, sse_manager: SSEManager, task_context_map: Dict[str, Dict], task_context_lock: threading.Lock, app_name: str)` - A service for managing A2A task operations.
118
- - `cancel_task(agent_name: str, task_id: str, client_id: str, user_id: str = "web_user") -> None` - Asynchronously constructs and publishes an A2A `CancelTaskRequest` message for a specific task.
80
+ **Purpose:** Handles A2A task operations, specifically task cancellation using CoreA2AService and message publishing
81
+ **Import:** `from solace_agent_mesh.gateway.http_sse.services.task_service import TaskService, PublishFunc`
119
82
 
120
83
  **Type Aliases:**
121
- - `PublishFunc: Callable[[str, Dict, Optional[Dict]], None]` - A callable that sends a message. It takes a topic, a payload dictionary, and optional user properties.
84
+ - `PublishFunc: Callable[[str, Dict, Optional[Dict]], None]` - Function type for publishing messages (topic, payload, user_properties)
85
+
86
+ **Classes:**
87
+ - `TaskService(core_a2a_service: CoreA2AService, publish_func: PublishFunc, namespace: str, gateway_id: str, sse_manager: SSEManager, task_context_map: Dict[str, Dict], task_context_lock: threading.Lock, app_name: str)` - Service for managing A2A task operations
88
+ - `cancel_task(agent_name: str, task_id: str, client_id: str, user_id: str = "web_user") -> None` - Asynchronously cancels a task by publishing A2A CancelTaskRequest message
122
89
 
123
90
  **Usage Examples:**
124
91
  ```python
125
92
  import asyncio
126
93
  import threading
127
- from typing import Callable, Dict, Optional
128
-
129
- from src.solace_agent_mesh.gateway.http_sse.services.task_service import TaskService, PublishFunc
130
- from src.solace_agent_mesh.core_a2a.service import CoreA2AService
131
- from src.solace_agent_mesh.gateway.http_sse.sse_manager import SSEManager
132
-
133
- # Mock dependencies for the example
134
- class MockCoreA2AService(CoreA2AService):
135
- def cancel_task(self, agent_name, task_id, client_id, user_id):
136
- topic = f"a2a/request/{agent_name}/cancelTask"
137
- payload = {"taskId": task_id}
138
- user_props = {"clientId": client_id, "userId": user_id}
139
- return topic, payload, user_props
140
-
141
- def my_publish_func(topic: str, payload: Dict, user_properties: Optional[Dict]):
142
- print("\n--- Publishing Message ---")
143
- print(f"Topic: {topic}")
144
- print(f"Payload: {payload}")
145
- print(f"User Properties: {user_properties}")
146
- print("------------------------")
147
-
148
- async def main():
149
- # 1. Set up dependencies
150
- core_a2a_service = MockCoreA2AService()
151
- sse_manager = SSEManager()
152
- task_context_map = {}
153
- task_context_lock = threading.Lock()
154
-
155
- # 2. Initialize TaskService
156
- task_service = TaskService(
157
- core_a2a_service=core_a2a_service,
158
- publish_func=my_publish_func,
159
- namespace="my-namespace",
160
- gateway_id="gateway-01",
161
- sse_manager=sse_manager,
162
- task_context_map=task_context_map,
163
- task_context_lock=task_context_lock,
164
- app_name="my-app"
165
- )
166
-
167
- # 3. Call the cancel_task method
168
- print("Requesting task cancellation...")
94
+ from solace_agent_mesh.gateway.http_sse.services.task_service import TaskService, PublishFunc
95
+ from solace_agent_mesh.core_a2a.service import CoreA2AService
96
+ from solace_agent_mesh.gateway.http_sse.sse_manager import SSEManager
97
+
98
+ # Define publish function
99
+ def my_publish_func(topic: str, payload: dict, user_properties: dict = None):
100
+ print(f"Publishing to {topic}: {payload}")
101
+ # Your actual message publishing logic here
102
+
103
+ # Initialize dependencies
104
+ core_a2a_service = CoreA2AService() # Your core A2A service
105
+ sse_manager = SSEManager()
106
+ task_context_map = {}
107
+ task_context_lock = threading.Lock()
108
+
109
+ # Create task service
110
+ task_service = TaskService(
111
+ core_a2a_service=core_a2a_service,
112
+ publish_func=my_publish_func,
113
+ namespace="my-namespace",
114
+ gateway_id="gateway-01",
115
+ sse_manager=sse_manager,
116
+ task_context_map=task_context_map,
117
+ task_context_lock=task_context_lock,
118
+ app_name="my-app"
119
+ )
120
+
121
+ async def cancel_task_example():
122
+ # Cancel a task
169
123
  await task_service.cancel_task(
170
- agent_name="report-generator",
171
- task_id="task-12345",
172
- client_id="client-abcde",
173
- user_id="test.user"
124
+ agent_name="data-processor",
125
+ task_id="task-123",
126
+ client_id="client-456",
127
+ user_id="user@example.com"
174
128
  )
175
- print("Task cancellation request sent.")
176
129
 
177
- if __name__ == "__main__":
178
- asyncio.run(main())
179
- ```
130
+ asyncio.run(cancel_task_example())
131
+ ```
132
+
133
+ # content_hash: 83ddf6b403dc50598ed550e4b3a5445f832b3956dad75f7a3fbbb7e6e5c6c115
@@ -8,10 +8,7 @@ from typing import Callable, Dict, Optional
8
8
 
9
9
  from solace_ai_connector.common.log import log
10
10
 
11
- from ....common.types import (
12
- InternalError,
13
- )
14
-
11
+ from ....common import a2a
15
12
  from ....gateway.http_sse.sse_manager import SSEManager
16
13
  from ....core_a2a.service import CoreA2AService
17
14
 
@@ -116,6 +113,6 @@ class TaskService:
116
113
 
117
114
  except Exception as e:
118
115
  log.exception("%sFailed to publish cancellation request: %s", log_prefix, e)
119
- raise InternalError(
116
+ raise a2a.create_internal_error(
120
117
  message="Failed to publish cancellation request: %s" % e
121
118
  ) from e
@@ -3,10 +3,13 @@ Manages web user sessions and mapping to A2A Client IDs.
3
3
  """
4
4
 
5
5
  import uuid
6
- from starlette.requests import Request
7
- from typing import Optional, Callable, Dict, Any
6
+ from collections.abc import Callable
7
+ from typing import Any
8
8
 
9
9
  from solace_ai_connector.common.log import log
10
+ from starlette.requests import Request
11
+
12
+ from .infrastructure.persistence_service import PersistenceService
10
13
 
11
14
  SESSION_KEY_CLIENT_ID = "a2a_client_id"
12
15
  SESSION_KEY_SESSION_ID = "a2a_session_id"
@@ -21,12 +24,18 @@ class SessionManager:
21
24
  Generates and stores unique A2A Client IDs and manages the current A2A Session ID per web session.
22
25
  """
23
26
 
24
- def __init__(self, secret_key: str, app_config: Dict[str, Any]):
27
+ def __init__(
28
+ self,
29
+ secret_key: str,
30
+ app_config: dict[str, Any],
31
+ persistence_service: "PersistenceService",
32
+ ):
25
33
  if not secret_key:
26
34
  raise ValueError("Session secret key cannot be empty.")
27
35
  self.secret_key = secret_key
28
36
  self.force_user_identity = app_config.get("force_user_identity")
29
- self.default_user_identity = app_config.get("default_user_identity")
37
+ self.use_authorization = app_config.get("frontend_use_authorization", False)
38
+ self.persistence_service = persistence_service
30
39
  self._temp_code_cache = {}
31
40
  log.info("[SessionManager] Initialized.")
32
41
  if self.force_user_identity:
@@ -34,10 +43,11 @@ class SessionManager:
34
43
  f"[SessionManager] Forcing user identity to: {self.force_user_identity}"
35
44
  )
36
45
 
37
- def _get_or_create_client_id(self, request: Request) -> str:
46
+ def _get_or_create_client_id(self, request: Request) -> str | None:
38
47
  """
39
48
  Retrieves the A2A Client ID. It prioritizes the authenticated user from
40
49
  `request.state.user` and falls back to session-based or generated IDs.
50
+ If authorization is enabled, it returns None if no user can be identified.
41
51
  """
42
52
  if self.force_user_identity:
43
53
  return self.force_user_identity
@@ -64,35 +74,35 @@ class SessionManager:
64
74
  return user_id
65
75
 
66
76
  client_id = request.session.get(SESSION_KEY_CLIENT_ID)
67
- if not client_id:
68
- if self.default_user_identity:
69
- log.info(
70
- "[SessionManager] Using default_user_identity as A2A Client ID: %s",
71
- self.default_user_identity,
72
- )
73
- client_id = self.default_user_identity
74
- else:
75
- client_id = f"web-client-{uuid.uuid4().hex}"
76
- log.info(
77
- "[SessionManager] Created new A2A Client ID: %s for web session.",
78
- client_id,
79
- )
80
- request.session[SESSION_KEY_CLIENT_ID] = client_id
81
- else:
77
+ if client_id:
82
78
  log.debug(
83
79
  "[SessionManager] Using existing A2A Client ID: %s for web session.",
84
80
  client_id,
85
81
  )
86
- return client_id
82
+ return client_id
83
+
84
+ if not self.use_authorization:
85
+ client_id = "sam_dev_user"
86
+ log.info(
87
+ "[SessionManager] No authenticated user and auth is disabled, using client ID: %s for web session.",
88
+ client_id,
89
+ )
90
+ request.session[SESSION_KEY_CLIENT_ID] = client_id
91
+ return client_id
92
+
93
+ log.warning(
94
+ "[SessionManager] Could not determine client ID and authorization is enabled."
95
+ )
96
+ return None
87
97
 
88
- def get_a2a_client_id(self, request: Request) -> str:
98
+ def get_a2a_client_id(self, request: Request) -> str | None:
89
99
  """
90
100
  FastAPI dependency callable to get the A2A Client ID for the current request.
91
- Ensures a client ID exists in the session.
101
+ Ensures a client ID exists in the session if auth is disabled.
92
102
  """
93
103
  return self._get_or_create_client_id(request)
94
104
 
95
- def get_a2a_session_id(self, request: Request) -> Optional[str]:
105
+ def get_a2a_session_id(self, request: Request) -> str | None:
96
106
  """
97
107
  FastAPI dependency callable to get the current A2A Session ID for the current request.
98
108
  Returns None if no session has been started for the current agent in this web session.
@@ -107,6 +117,11 @@ class SessionManager:
107
117
  This should be called when the user explicitly starts a new chat or switches agents.
108
118
  """
109
119
  client_id = self._get_or_create_client_id(request)
120
+ if not client_id:
121
+ # This case should ideally be prevented by middleware raising 401
122
+ raise RuntimeError(
123
+ "Cannot start a new A2A session without a client ID when authorization is enabled."
124
+ )
110
125
  new_session_id = f"web-session-{uuid.uuid4().hex}"
111
126
  request.session[SESSION_KEY_SESSION_ID] = new_session_id
112
127
  log.info(
@@ -116,6 +131,25 @@ class SessionManager:
116
131
  )
117
132
  return new_session_id
118
133
 
134
+ def create_new_session_id(self, request: Request) -> str:
135
+ """
136
+ Generates a new A2A Session ID without storing it in cookies.
137
+ This should be used when the frontend manages session state.
138
+ """
139
+ client_id = self._get_or_create_client_id(request)
140
+ if not client_id:
141
+ # This case should ideally be prevented by middleware raising 401
142
+ raise RuntimeError(
143
+ "Cannot start a new A2A session without a client ID when authorization is enabled."
144
+ )
145
+ new_session_id = f"web-session-{uuid.uuid4().hex}"
146
+ log.info(
147
+ "[SessionManager] Generated new A2A Session ID: %s for Client ID: %s (not stored in cookies)",
148
+ new_session_id,
149
+ client_id,
150
+ )
151
+ return new_session_id
152
+
119
153
  def ensure_a2a_session(self, request: Request) -> str:
120
154
  """
121
155
  Ensures an A2A session ID exists, creating one if necessary.
@@ -131,7 +165,7 @@ class SessionManager:
131
165
  return session_id
132
166
 
133
167
  def store_auth_tokens(
134
- self, request: Request, access_token: str, refresh_token: Optional[str] = None
168
+ self, request: Request, access_token: str, refresh_token: str | None = None
135
169
  ):
136
170
  """
137
171
  Stores authentication tokens directly in the user's session.
@@ -141,13 +175,13 @@ class SessionManager:
141
175
  request.session[SESSION_KEY_REFRESH_TOKEN] = refresh_token
142
176
  log.info("[SessionManager] Stored auth tokens directly in session.")
143
177
 
144
- def get_access_token(self, request: Request) -> Optional[str]:
178
+ def get_access_token(self, request: Request) -> str | None:
145
179
  """
146
180
  Retrieves the access token from the web session.
147
181
  """
148
182
  return request.session.get(SESSION_KEY_ACCESS_TOKEN)
149
183
 
150
- def get_refresh_token(self, request: Request) -> Optional[str]:
184
+ def get_refresh_token(self, request: Request) -> str | None:
151
185
  """
152
186
  Retrieves the refresh token from the web session.
153
187
  """
@@ -168,17 +202,17 @@ class SessionManager:
168
202
  request.session[SESSION_KEY_USER_ID] = user_id
169
203
  log.info("[SessionManager] Stored user ID in session: %s", user_id)
170
204
 
171
- def get_user_id(self, request: Request) -> Optional[str]:
205
+ def get_user_id(self, request: Request) -> str | None:
172
206
  """
173
207
  Retrieves the user ID from the web session.
174
208
  """
175
209
  return request.session.get(SESSION_KEY_USER_ID)
176
210
 
177
- def dep_get_client_id(self) -> Callable[[Request], str]:
211
+ def dep_get_client_id(self) -> Callable[[Request], str | None]:
178
212
  """Returns a callable suitable for FastAPI Depends to get the client ID."""
179
213
  return self.get_a2a_client_id
180
214
 
181
- def dep_get_session_id(self) -> Callable[[Request], Optional[str]]:
215
+ def dep_get_session_id(self) -> Callable[[Request], str | None]:
182
216
  """Returns a callable suitable for FastAPI Depends to get the current session ID."""
183
217
  return self.get_a2a_session_id
184
218
 
@@ -0,0 +1,9 @@
1
+ """
2
+ Shared Utilities and Constants
3
+
4
+ Contains common utilities, constants, enums, and types used across layers.
5
+ """
6
+
7
+ from .auth_utils import get_current_user
8
+
9
+ __all__ = ["get_current_user"]
@@ -0,0 +1,29 @@
1
+ """
2
+ Authentication utilities for the FastAPI application.
3
+
4
+ This module provides common authentication functions used across controllers.
5
+ """
6
+
7
+ from fastapi import Depends, Request as FastAPIRequest
8
+
9
+
10
+ async def get_current_user(request: FastAPIRequest) -> dict:
11
+ """
12
+ Extracts the current user from the request state.
13
+
14
+ This function is used as a FastAPI dependency to get the authenticated user
15
+ information that was set by the AuthMiddleware.
16
+
17
+ Args:
18
+ request: The FastAPI request object with user state
19
+
20
+ Returns:
21
+ dict: User information dictionary containing id, name, email, etc.
22
+ """
23
+ return getattr(request.state, "user", {
24
+ "id": "anonymous",
25
+ "name": "Anonymous User",
26
+ "email": "anonymous@localhost",
27
+ "authenticated": False,
28
+ "auth_method": "none"
29
+ })
@@ -0,0 +1,45 @@
1
+ """
2
+ Enumerations used throughout the application.
3
+ """
4
+
5
+ from enum import Enum
6
+
7
+
8
+ class SenderType(str, Enum):
9
+ """Types of message senders."""
10
+ USER = "user"
11
+ AGENT = "agent"
12
+ SYSTEM = "system"
13
+
14
+
15
+ class TaskStatus(str, Enum):
16
+ """Task execution status."""
17
+ PENDING = "pending"
18
+ RUNNING = "running"
19
+ COMPLETED = "completed"
20
+ FAILED = "failed"
21
+ CANCELLED = "cancelled"
22
+
23
+
24
+ class SessionStatus(str, Enum):
25
+ """Session status."""
26
+ ACTIVE = "active"
27
+ INACTIVE = "inactive"
28
+ ARCHIVED = "archived"
29
+
30
+
31
+ class MessageType(str, Enum):
32
+ """Types of messages."""
33
+ TEXT = "text"
34
+ FILE = "file"
35
+ IMAGE = "image"
36
+ DOCUMENT = "document"
37
+
38
+
39
+ class ValidationErrorType(str, Enum):
40
+ """Types of validation errors."""
41
+ REQUIRED_FIELD = "required_field"
42
+ INVALID_FORMAT = "invalid_format"
43
+ OUT_OF_RANGE = "out_of_range"
44
+ DUPLICATE_VALUE = "duplicate_value"
45
+ BUSINESS_RULE = "business_rule"
@@ -0,0 +1,45 @@
1
+ """
2
+ Custom types and type aliases used throughout the application.
3
+ """
4
+
5
+ from typing import Dict, Any, List, Optional, Union
6
+ from datetime import datetime
7
+ from pydantic import BaseModel
8
+
9
+ # Basic type aliases
10
+ UserId = str
11
+ SessionId = str
12
+ MessageId = str
13
+ TaskId = str
14
+ AgentId = str
15
+
16
+ # Dictionary types
17
+ JsonDict = Dict[str, Any]
18
+ Headers = Dict[str, str]
19
+ QueryParams = Dict[str, Union[str, List[str]]]
20
+
21
+ # Common data structures
22
+ class Timestamp(BaseModel):
23
+ """Standardized timestamp representation."""
24
+ created_at: datetime
25
+ updated_at: Optional[datetime] = None
26
+
27
+ class PaginationInfo(BaseModel):
28
+ """Pagination information for list responses."""
29
+ page: int
30
+ page_size: int
31
+ total_items: int
32
+ total_pages: int
33
+ has_next: bool
34
+ has_previous: bool
35
+
36
+ class SortInfo(BaseModel):
37
+ """Sorting information for list requests."""
38
+ field: str
39
+ direction: str = "asc" # asc or desc
40
+
41
+ class FilterInfo(BaseModel):
42
+ """Filtering information for list requests."""
43
+ field: str
44
+ operator: str # eq, ne, gt, lt, gte, lte, contains, in
45
+ value: Any