solace-agent-mesh 1.6.0__py3-none-any.whl → 1.6.2__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 (127) hide show
  1. solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
  2. solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +1 -1
  3. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +135 -31
  4. solace_agent_mesh/agent/adk/models/lite_llm.py +5 -0
  5. solace_agent_mesh/agent/adk/runner.py +10 -12
  6. solace_agent_mesh/agent/adk/services.py +50 -14
  7. solace_agent_mesh/agent/adk/setup.py +66 -38
  8. solace_agent_mesh/agent/protocol/event_handlers.py +416 -152
  9. solace_agent_mesh/agent/proxies/a2a/app.py +3 -2
  10. solace_agent_mesh/agent/proxies/base/app.py +3 -2
  11. solace_agent_mesh/agent/proxies/base/component.py +35 -4
  12. solace_agent_mesh/agent/sac/app.py +97 -9
  13. solace_agent_mesh/agent/sac/component.py +284 -145
  14. solace_agent_mesh/agent/sac/task_execution_context.py +79 -2
  15. solace_agent_mesh/agent/tools/tool_config_types.py +3 -0
  16. solace_agent_mesh/agent/utils/artifact_helpers.py +1 -1
  17. solace_agent_mesh/assets/docs/404.html +3 -3
  18. solace_agent_mesh/assets/docs/assets/js/240a0364.c39f8388.js +1 -0
  19. solace_agent_mesh/assets/docs/assets/js/631738c7.7c4594c9.js +1 -0
  20. solace_agent_mesh/assets/docs/assets/js/66d4869e.830d443f.js +1 -0
  21. solace_agent_mesh/assets/docs/assets/js/71da7b71.ddbdfbe2.js +1 -0
  22. solace_agent_mesh/assets/docs/assets/js/{e3d9abda.2b916f9e.js → e3d9abda.6b9493d0.js} +1 -1
  23. solace_agent_mesh/assets/docs/assets/js/e92d0134.4f395c6b.js +1 -0
  24. solace_agent_mesh/assets/docs/assets/js/f284c35a.720d2ef2.js +1 -0
  25. solace_agent_mesh/assets/docs/assets/js/main.d1643f0b.js +2 -0
  26. solace_agent_mesh/assets/docs/assets/js/runtime~main.97f920d4.js +1 -0
  27. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +3 -3
  28. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +3 -3
  29. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +3 -3
  30. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +3 -3
  31. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +3 -3
  32. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +3 -3
  33. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +3 -3
  34. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +3 -3
  35. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +3 -3
  36. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +3 -3
  37. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +3 -3
  38. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +3 -3
  39. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +4 -25
  40. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +4 -4
  41. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +4 -4
  42. solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +76 -0
  43. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +5 -4
  44. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +3 -3
  45. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +3 -3
  46. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +3 -3
  47. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +3 -3
  48. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +3 -3
  49. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +3 -3
  50. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +3 -3
  51. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +3 -3
  52. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +3 -3
  53. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +3 -3
  54. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +3 -3
  55. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +3 -3
  56. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +3 -3
  57. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +3 -3
  58. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +3 -3
  59. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +3 -3
  60. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +3 -3
  61. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +3 -3
  62. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +3 -3
  63. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +3 -3
  64. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +3 -3
  65. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +3 -3
  66. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +3 -3
  67. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +3 -3
  68. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +3 -6
  69. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +3 -3
  70. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +3 -3
  71. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +3 -3
  72. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +3 -3
  73. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +3 -3
  74. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +3 -3
  75. solace_agent_mesh/assets/docs/lunr-index-1761663789856.json +1 -0
  76. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  77. solace_agent_mesh/assets/docs/search-doc-1761663789856.json +1 -0
  78. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  79. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  80. solace_agent_mesh/cli/__init__.py +1 -1
  81. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-BTf6dqwp.js → authCallback-D4_RMYRh.js} +1 -1
  82. solace_agent_mesh/client/webui/frontend/static/assets/{client-CaY59VuC.js → client-UZ3qU6Bq.js} +1 -1
  83. solace_agent_mesh/client/webui/frontend/static/assets/main--3yJYl7S.css +1 -0
  84. solace_agent_mesh/client/webui/frontend/static/assets/main-DojKHS49.js +342 -0
  85. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BEmvJSYz.js → vendor-DSqhjwq_.js} +1 -1
  86. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  87. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  88. solace_agent_mesh/common/a2a/events.py +2 -1
  89. solace_agent_mesh/common/a2a/protocol.py +78 -0
  90. solace_agent_mesh/common/sac/sam_component_base.py +406 -21
  91. solace_agent_mesh/common/utils/pydantic_utils.py +90 -3
  92. solace_agent_mesh/gateway/base/app.py +15 -0
  93. solace_agent_mesh/gateway/base/component.py +116 -46
  94. solace_agent_mesh/gateway/http_sse/app.py +7 -0
  95. solace_agent_mesh/gateway/http_sse/component.py +18 -10
  96. solace_agent_mesh/gateway/http_sse/dependencies.py +83 -59
  97. solace_agent_mesh/gateway/http_sse/main.py +5 -4
  98. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +1 -1
  99. solace_agent_mesh/gateway/http_sse/routers/auth.py +103 -6
  100. solace_agent_mesh/gateway/http_sse/routers/config.py +1 -1
  101. solace_agent_mesh/gateway/http_sse/routers/sessions.py +1 -1
  102. solace_agent_mesh/gateway/http_sse/routers/sse.py +15 -5
  103. solace_agent_mesh/gateway/http_sse/routers/tasks.py +3 -3
  104. solace_agent_mesh/gateway/http_sse/routers/users.py +47 -1
  105. solace_agent_mesh/gateway/http_sse/routers/visualization.py +90 -8
  106. solace_agent_mesh/gateway/http_sse/services/session_service.py +1 -1
  107. solace_agent_mesh/gateway/http_sse/session_manager.py +15 -15
  108. solace_agent_mesh/gateway/http_sse/shared/exception_handlers.py +16 -1
  109. solace_agent_mesh/gateway/http_sse/sse_manager.py +15 -6
  110. solace_agent_mesh/templates/logging_config_template.ini +2 -2
  111. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/METADATA +2 -2
  112. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/RECORD +116 -114
  113. solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +0 -1
  114. solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +0 -1
  115. solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +0 -1
  116. solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +0 -1
  117. solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +0 -1
  118. solace_agent_mesh/assets/docs/assets/js/main.20feee82.js +0 -2
  119. solace_agent_mesh/assets/docs/assets/js/runtime~main.0d198646.js +0 -1
  120. solace_agent_mesh/assets/docs/lunr-index-1761165361160.json +0 -1
  121. solace_agent_mesh/assets/docs/search-doc-1761165361160.json +0 -1
  122. solace_agent_mesh/client/webui/frontend/static/assets/main-BGTaW0uv.js +0 -342
  123. solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +0 -1
  124. /solace_agent_mesh/assets/docs/assets/js/{main.20feee82.js.LICENSE.txt → main.d1643f0b.js.LICENSE.txt} +0 -0
  125. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/WHEEL +0 -0
  126. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/entry_points.txt +0 -0
  127. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/licenses/LICENSE +0 -0
@@ -5,7 +5,6 @@ managed by the WebUIBackendComponent.
5
5
 
6
6
  import logging
7
7
  from collections.abc import Callable, Generator
8
- from contextlib import contextmanager
9
8
  from typing import TYPE_CHECKING, Any
10
9
 
11
10
  from fastapi import Depends, HTTPException, Request, status
@@ -18,11 +17,11 @@ from ...common.services.identity_service import BaseIdentityService
18
17
  from ...core_a2a.service import CoreA2AService
19
18
  from ...gateway.base.task_context import TaskContextManager
20
19
  from ...gateway.http_sse.services.agent_card_service import AgentCardService
21
- from ...gateway.http_sse.services.people_service import PeopleService
22
- from ...gateway.http_sse.services.task_service import TaskService
20
+ from ...gateway.http_sse.services.data_retention_service import DataRetentionService
23
21
  from ...gateway.http_sse.services.feedback_service import FeedbackService
22
+ from ...gateway.http_sse.services.people_service import PeopleService
24
23
  from ...gateway.http_sse.services.task_logger_service import TaskLoggerService
25
- from ...gateway.http_sse.services.data_retention_service import DataRetentionService
24
+ from ...gateway.http_sse.services.task_service import TaskService
26
25
  from ...gateway.http_sse.session_manager import SessionManager
27
26
  from ...gateway.http_sse.sse_manager import SSEManager
28
27
  from .repository import SessionRepository
@@ -54,32 +53,57 @@ def set_component_instance(component: "WebUIBackendComponent"):
54
53
  global sac_component_instance
55
54
  if sac_component_instance is None:
56
55
  sac_component_instance = component
57
- log.info("[Dependencies] SAC Component instance provided.")
56
+ log.info("SAC Component instance provided.")
58
57
  else:
59
- log.warning("[Dependencies] SAC Component instance already set.")
58
+ log.warning("SAC Component instance already set.")
60
59
 
61
60
 
62
61
  def init_database(database_url: str):
63
- """Initialize database with direct sessionmaker."""
62
+ """Initialize database with appropriate configuration based on database dialect."""
64
63
  global SessionLocal
65
64
  if SessionLocal is None:
66
- engine = create_engine(database_url)
65
+ from sqlalchemy import event, pool
66
+ from sqlalchemy.engine.url import make_url
67
+
68
+ url = make_url(database_url)
69
+ dialect_name = url.get_dialect().name
70
+
71
+ engine_kwargs = {}
72
+
73
+ if dialect_name == "sqlite":
74
+ engine_kwargs = {
75
+ "poolclass": pool.StaticPool,
76
+ "connect_args": {"check_same_thread": False}
77
+ }
78
+ log.info("Configuring SQLite database (single-connection mode)")
79
+
80
+ elif dialect_name in ("postgresql", "mysql"):
81
+ engine_kwargs = {
82
+ "pool_size": 10,
83
+ "max_overflow": 20,
84
+ "pool_timeout": 30,
85
+ "pool_recycle": 1800,
86
+ "pool_pre_ping": True,
87
+ }
88
+ log.info(f"Configuring {dialect_name} database with connection pooling")
89
+
90
+ else:
91
+ log.warning(f"Using default configuration for dialect: {dialect_name}")
67
92
 
68
- # Enable foreign keys for SQLite only (database-agnostic)
69
- from sqlalchemy import event
93
+ engine = create_engine(database_url, **engine_kwargs)
70
94
 
71
95
  @event.listens_for(engine, "connect")
72
96
  def set_sqlite_pragma(dbapi_conn, connection_record):
73
- # Only apply to SQLite connections
74
- if database_url.startswith("sqlite"):
97
+ if dialect_name == "sqlite":
75
98
  cursor = dbapi_conn.cursor()
76
99
  cursor.execute("PRAGMA foreign_keys=ON")
77
100
  cursor.close()
78
101
 
79
102
  SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
80
- log.info("[Dependencies] Database initialized with foreign key support.")
103
+ log.debug(f"Database initialized: {url}")
104
+ log.info("Database initialized successfully")
81
105
  else:
82
- log.warning("[Dependencies] Database already initialized.")
106
+ log.warning("Database already initialized.")
83
107
 
84
108
 
85
109
  def set_api_config(config: dict[str, Any]):
@@ -87,16 +111,16 @@ def set_api_config(config: dict[str, Any]):
87
111
  global api_config
88
112
  if api_config is None:
89
113
  api_config = config
90
- log.info("[Dependencies] API configuration provided.")
114
+ log.debug("API configuration provided.")
91
115
  else:
92
- log.warning("[Dependencies] API configuration already set.")
116
+ log.warning("API configuration already set.")
93
117
 
94
118
 
95
119
  def get_sac_component() -> "WebUIBackendComponent":
96
120
  """FastAPI dependency to get the SAC component instance."""
97
121
  if sac_component_instance is None:
98
122
  log.critical(
99
- "[Dependencies] SAC Component instance accessed before it was set!"
123
+ "SAC Component instance accessed before it was set!"
100
124
  )
101
125
  raise HTTPException(
102
126
  status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
@@ -108,7 +132,7 @@ def get_sac_component() -> "WebUIBackendComponent":
108
132
  def get_api_config() -> dict[str, Any]:
109
133
  """FastAPI dependency to get the API configuration."""
110
134
  if api_config is None:
111
- log.critical("[Dependencies] API configuration accessed before it was set!")
135
+ log.critical("API configuration accessed before it was set!")
112
136
  raise HTTPException(
113
137
  status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
114
138
  detail="API configuration not yet initialized.",
@@ -120,7 +144,7 @@ def get_agent_registry(
120
144
  component: "WebUIBackendComponent" = Depends(get_sac_component),
121
145
  ) -> AgentRegistry:
122
146
  """FastAPI dependency to get the AgentRegistry."""
123
- log.debug("[Dependencies] get_agent_registry called")
147
+ log.debug("get_agent_registry called")
124
148
  return component.get_agent_registry()
125
149
 
126
150
 
@@ -128,7 +152,7 @@ def get_sse_manager(
128
152
  component: "WebUIBackendComponent" = Depends(get_sac_component),
129
153
  ) -> SSEManager:
130
154
  """FastAPI dependency to get the SSEManager."""
131
- log.debug("[Dependencies] get_sse_manager called")
155
+ log.debug("get_sse_manager called")
132
156
  return component.get_sse_manager()
133
157
 
134
158
 
@@ -136,7 +160,7 @@ def get_session_manager(
136
160
  component: "WebUIBackendComponent" = Depends(get_sac_component),
137
161
  ) -> SessionManager:
138
162
  """FastAPI dependency to get the SessionManager."""
139
- log.debug("[Dependencies] get_session_manager called")
163
+ log.debug("get_session_manager called")
140
164
  return component.get_session_manager()
141
165
 
142
166
 
@@ -144,7 +168,7 @@ def get_user_id_callable(
144
168
  session_manager: SessionManager = Depends(get_session_manager),
145
169
  ) -> Callable:
146
170
  """Dependency that provides the callable for getting user_id (client_id)."""
147
- log.debug("[Dependencies] Providing user_id callable")
171
+ log.debug("Providing user_id callable")
148
172
  return session_manager.dep_get_client_id()
149
173
 
150
174
 
@@ -152,7 +176,7 @@ def ensure_session_id_callable(
152
176
  session_manager: SessionManager = Depends(get_session_manager),
153
177
  ) -> Callable:
154
178
  """Dependency that provides the callable for ensuring session_id."""
155
- log.debug("[Dependencies] Providing ensure_session_id callable")
179
+ log.debug("Providing ensure_session_id callable")
156
180
  return session_manager.dep_ensure_session_id()
157
181
 
158
182
 
@@ -165,17 +189,17 @@ def get_user_id(
165
189
  When FRONTEND_USE_AUTHORIZATION is true: Fully relies on OAuth - user must be authenticated by AuthMiddleware.
166
190
  When FRONTEND_USE_AUTHORIZATION is false: Uses development fallback user.
167
191
  """
168
- log.debug("[Dependencies] Resolving user_id string")
192
+ log.debug("Resolving user_id string")
169
193
 
170
194
  # AuthMiddleware should always set user state for both auth enabled/disabled cases
171
195
  if hasattr(request.state, "user") and request.state.user:
172
196
  user_id = request.state.user.get("id")
173
197
  if user_id:
174
- log.debug(f"[Dependencies] Using user ID from AuthMiddleware: {user_id}")
198
+ log.debug(f"Using user ID from AuthMiddleware: {user_id}")
175
199
  return user_id
176
200
  else:
177
201
  log.error(
178
- "[Dependencies] request.state.user exists but has no 'id' field: %s. This indicates a bug in AuthMiddleware.",
202
+ "request.state.user exists but has no 'id' field: %s. This indicates a bug in AuthMiddleware.",
179
203
  request.state.user,
180
204
  )
181
205
 
@@ -185,7 +209,7 @@ def get_user_id(
185
209
  if use_authorization:
186
210
  # When OAuth is enabled, we should never reach here - AuthMiddleware should have handled authentication
187
211
  log.error(
188
- "[Dependencies] OAuth is enabled but no authenticated user found. This indicates an authentication failure or middleware bug."
212
+ "OAuth is enabled but no authenticated user found. This indicates an authentication failure or middleware bug."
189
213
  )
190
214
  raise HTTPException(
191
215
  status_code=status.HTTP_401_UNAUTHORIZED,
@@ -195,7 +219,7 @@ def get_user_id(
195
219
  # When auth is disabled, use development fallback user
196
220
  fallback_id = "sam_dev_user"
197
221
  log.info(
198
- "[Dependencies] Authorization disabled and no user in request state, using fallback user: %s",
222
+ "Authorization disabled and no user in request state, using fallback user: %s",
199
223
  fallback_id,
200
224
  )
201
225
  return fallback_id
@@ -206,7 +230,7 @@ def ensure_session_id(
206
230
  session_manager: SessionManager = Depends(get_session_manager),
207
231
  ) -> str:
208
232
  """FastAPI dependency that directly returns the ensured session_id string."""
209
- log.debug("[Dependencies] Resolving ensured session_id string")
233
+ log.debug("Resolving ensured session_id string")
210
234
  return session_manager.ensure_a2a_session(request)
211
235
 
212
236
 
@@ -214,7 +238,7 @@ def get_identity_service(
214
238
  component: "WebUIBackendComponent" = Depends(get_sac_component),
215
239
  ) -> BaseIdentityService | None:
216
240
  """FastAPI dependency to get the configured IdentityService instance."""
217
- log.debug("[Dependencies] get_identity_service called")
241
+ log.debug("get_identity_service called")
218
242
  return component.identity_service
219
243
 
220
244
 
@@ -239,13 +263,13 @@ def get_people_service(
239
263
  identity_service: BaseIdentityService | None = Depends(get_identity_service),
240
264
  ) -> PeopleService:
241
265
  """FastAPI dependency to get an instance of PeopleService."""
242
- log.debug("[Dependencies] get_people_service called")
266
+ log.debug("get_people_service called")
243
267
  return PeopleService(identity_service=identity_service)
244
268
 
245
269
 
246
270
  def get_task_repository() -> ITaskRepository:
247
271
  """FastAPI dependency to get an instance of TaskRepository."""
248
- log.debug("[Dependencies] get_task_repository called")
272
+ log.debug("get_task_repository called")
249
273
  return TaskRepository()
250
274
 
251
275
 
@@ -254,7 +278,7 @@ def get_feedback_service(
254
278
  task_repo: ITaskRepository = Depends(get_task_repository),
255
279
  ) -> FeedbackService:
256
280
  """FastAPI dependency to get an instance of FeedbackService."""
257
- log.debug("[Dependencies] get_feedback_service called")
281
+ log.debug("get_feedback_service called")
258
282
  # The session factory is needed for the existing DB save logic.
259
283
  session_factory = SessionLocal if component.database_url else None
260
284
  return FeedbackService(
@@ -277,11 +301,11 @@ def get_data_retention_service(
277
301
  data retention statistics or manual cleanup triggers. The service itself
278
302
  runs automatically via timer in the component.
279
303
  """
280
- log.debug("[Dependencies] get_data_retention_service called")
304
+ log.debug("get_data_retention_service called")
281
305
 
282
306
  if not component.database_url:
283
307
  log.debug(
284
- "[Dependencies] Database not configured, returning None for data retention service"
308
+ "Database not configured, returning None for data retention service"
285
309
  )
286
310
  return None
287
311
 
@@ -289,7 +313,7 @@ def get_data_retention_service(
289
313
  not hasattr(component, "data_retention_service")
290
314
  or component.data_retention_service is None
291
315
  ):
292
- log.warning("[Dependencies] DataRetentionService not initialized on component")
316
+ log.warning("DataRetentionService not initialized on component")
293
317
  return None
294
318
 
295
319
  return component.data_retention_service
@@ -299,10 +323,10 @@ def get_task_logger_service(
299
323
  component: "WebUIBackendComponent" = Depends(get_sac_component),
300
324
  ) -> TaskLoggerService:
301
325
  """FastAPI dependency to get an instance of TaskLoggerService."""
302
- log.debug("[Dependencies] get_task_logger_service called")
326
+ log.debug("get_task_logger_service called")
303
327
  task_logger_service = component.get_task_logger_service()
304
328
  if task_logger_service is None:
305
- log.error("[Dependencies] TaskLoggerService is not available.")
329
+ log.error("TaskLoggerService is not available.")
306
330
  raise HTTPException(
307
331
  status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
308
332
  detail="Task logging service is not configured or available.",
@@ -317,7 +341,7 @@ def get_publish_a2a_func(
317
341
  component: "WebUIBackendComponent" = Depends(get_sac_component),
318
342
  ) -> PublishFunc:
319
343
  """FastAPI dependency to get the component's publish_a2a method."""
320
- log.debug("[Dependencies] get_publish_a2a_func called")
344
+ log.debug("get_publish_a2a_func called")
321
345
  return component.publish_a2a
322
346
 
323
347
 
@@ -325,7 +349,7 @@ def get_namespace(
325
349
  component: "WebUIBackendComponent" = Depends(get_sac_component),
326
350
  ) -> str:
327
351
  """FastAPI dependency to get the namespace."""
328
- log.debug("[Dependencies] get_namespace called")
352
+ log.debug("get_namespace called")
329
353
  return component.get_namespace()
330
354
 
331
355
 
@@ -333,7 +357,7 @@ def get_gateway_id(
333
357
  component: "WebUIBackendComponent" = Depends(get_sac_component),
334
358
  ) -> str:
335
359
  """FastAPI dependency to get the Gateway ID."""
336
- log.debug("[Dependencies] get_gateway_id called")
360
+ log.debug("get_gateway_id called")
337
361
  return component.get_gateway_id()
338
362
 
339
363
 
@@ -341,7 +365,7 @@ def get_config_resolver(
341
365
  component: "WebUIBackendComponent" = Depends(get_sac_component),
342
366
  ) -> ConfigResolver:
343
367
  """FastAPI dependency to get the ConfigResolver."""
344
- log.debug("[Dependencies] get_config_resolver called")
368
+ log.debug("get_config_resolver called")
345
369
  return component.get_config_resolver()
346
370
 
347
371
 
@@ -351,7 +375,7 @@ def get_app_config(
351
375
  """
352
376
  FastAPI dependency to safely get the application configuration dictionary.
353
377
  """
354
- log.debug("[Dependencies] get_app_config called")
378
+ log.debug("get_app_config called")
355
379
  return component.component_config.get("app_config", {})
356
380
 
357
381
 
@@ -365,7 +389,7 @@ async def get_user_config(
365
389
  """
366
390
  FastAPI dependency to get the user-specific configuration.
367
391
  """
368
- log.debug(f"[Dependencies] get_user_config called for user_id: {user_id}")
392
+ log.debug(f"get_user_config called for user_id: {user_id}")
369
393
  gateway_context = {
370
394
  "gateway_id": component.gateway_id,
371
395
  "gateway_app_config": app_config,
@@ -408,7 +432,7 @@ class ValidatedUserConfig:
408
432
  user_id = user_config.get("user_profile", {}).get("id")
409
433
 
410
434
  log.debug(
411
- f"[Dependencies] ValidatedUserConfig called for user_id: {user_id} with required scopes: {self.required_scopes}"
435
+ f"ValidatedUserConfig called for user_id: {user_id} with required scopes: {self.required_scopes}"
412
436
  )
413
437
 
414
438
  # Validate scopes
@@ -418,7 +442,7 @@ class ValidatedUserConfig:
418
442
  {},
419
443
  ):
420
444
  log.warning(
421
- f"[Dependencies] Authorization denied for user '{user_id}'. Required scopes: {self.required_scopes}"
445
+ f"Authorization denied for user '{user_id}'. Required scopes: {self.required_scopes}"
422
446
  )
423
447
  raise HTTPException(
424
448
  status_code=status.HTTP_403_FORBIDDEN,
@@ -432,7 +456,7 @@ def get_shared_artifact_service(
432
456
  component: "WebUIBackendComponent" = Depends(get_sac_component),
433
457
  ) -> BaseArtifactService | None:
434
458
  """FastAPI dependency to get the shared ArtifactService."""
435
- log.debug("[Dependencies] get_shared_artifact_service called")
459
+ log.debug("get_shared_artifact_service called")
436
460
  return component.get_shared_artifact_service()
437
461
 
438
462
 
@@ -440,7 +464,7 @@ def get_embed_config(
440
464
  component: "WebUIBackendComponent" = Depends(get_sac_component),
441
465
  ) -> dict[str, Any]:
442
466
  """FastAPI dependency to get embed-related configuration."""
443
- log.debug("[Dependencies] get_embed_config called")
467
+ log.debug("get_embed_config called")
444
468
  return component.get_embed_config()
445
469
 
446
470
 
@@ -448,10 +472,10 @@ def get_core_a2a_service(
448
472
  component: "WebUIBackendComponent" = Depends(get_sac_component),
449
473
  ) -> CoreA2AService:
450
474
  """FastAPI dependency to get the CoreA2AService."""
451
- log.debug("[Dependencies] get_core_a2a_service called")
475
+ log.debug("get_core_a2a_service called")
452
476
  core_service = component.get_core_a2a_service()
453
477
  if core_service is None:
454
- log.critical("[Dependencies] CoreA2AService accessed before initialization!")
478
+ log.critical("CoreA2AService accessed before initialization!")
455
479
  raise HTTPException(status_code=503, detail="Core service not ready.")
456
480
  return core_service
457
481
 
@@ -460,10 +484,10 @@ def get_task_context_manager_from_component(
460
484
  component: "WebUIBackendComponent" = Depends(get_sac_component),
461
485
  ) -> TaskContextManager:
462
486
  """FastAPI dependency to get the TaskContextManager from the component."""
463
- log.debug("[Dependencies] get_task_context_manager_from_component called")
487
+ log.debug("get_task_context_manager_from_component called")
464
488
  if component.task_context_manager is None:
465
489
  log.critical(
466
- "[Dependencies] TaskContextManager accessed before initialization!"
490
+ "TaskContextManager accessed before initialization!"
467
491
  )
468
492
  raise HTTPException(status_code=503, detail="Task context manager not ready.")
469
493
  return component.task_context_manager
@@ -473,7 +497,7 @@ def get_agent_card_service(
473
497
  registry: AgentRegistry = Depends(get_agent_registry),
474
498
  ) -> AgentCardService:
475
499
  """FastAPI dependency to get an instance of AgentCardService."""
476
- log.debug("[Dependencies] get_agent_card_service called")
500
+ log.debug("get_agent_card_service called")
477
501
  return AgentCardService(agent_registry=registry)
478
502
 
479
503
 
@@ -489,7 +513,7 @@ def get_task_service(
489
513
  component: "WebUIBackendComponent" = Depends(get_sac_component),
490
514
  ) -> TaskService:
491
515
  """FastAPI dependency to get an instance of TaskService."""
492
- log.debug("[Dependencies] get_task_service called")
516
+ log.debug("get_task_service called")
493
517
  app_name = component.get_config("name", "WebUIBackendApp")
494
518
  return TaskService(
495
519
  core_a2a_service=core_a2a_service,
@@ -506,7 +530,7 @@ def get_task_service(
506
530
  def get_session_business_service(
507
531
  component: "WebUIBackendComponent" = Depends(get_sac_component),
508
532
  ) -> SessionService:
509
- log.debug("[Dependencies] get_session_business_service called")
533
+ log.debug("get_session_business_service called")
510
534
 
511
535
  # Note: Session and message repositories will be created per request
512
536
  # when the SessionService methods receive the db parameter
@@ -516,7 +540,7 @@ def get_session_business_service(
516
540
  def get_session_validator(
517
541
  component: "WebUIBackendComponent" = Depends(get_sac_component),
518
542
  ) -> Callable[[str, str], bool]:
519
- log.debug("[Dependencies] get_session_validator called")
543
+ log.debug("get_session_validator called")
520
544
 
521
545
  if SessionLocal:
522
546
  log.debug("Using database-backed session validation")
@@ -532,7 +556,7 @@ def get_session_validator(
532
556
  return session_domain is not None
533
557
  finally:
534
558
  db.close()
535
- except:
559
+ except Exception:
536
560
  return False
537
561
 
538
562
  return validate_with_database
@@ -550,7 +574,7 @@ def get_session_validator(
550
574
  def get_db_optional() -> Generator[Session | None, None, None]:
551
575
  """Optional database dependency that returns None if database is not configured."""
552
576
  if SessionLocal is None:
553
- log.debug("[Dependencies] Database not configured, returning None")
577
+ log.debug("Database not configured, returning None")
554
578
  yield None
555
579
  else:
556
580
  db = SessionLocal()
@@ -570,7 +594,7 @@ def get_session_business_service_optional(
570
594
  """Optional session service dependency that returns None if database is not configured."""
571
595
  if SessionLocal is None:
572
596
  log.debug(
573
- "[Dependencies] Database not configured, returning None for session service"
597
+ "Database not configured, returning None for session service"
574
598
  )
575
599
  return None
576
600
  return SessionService(component=component)
@@ -97,8 +97,7 @@ async def _get_user_info(
97
97
 
98
98
  def _extract_user_identifier(user_info: dict) -> str:
99
99
  user_identifier = (
100
- user_info.get("user_id") # internal /user_info endpoint format maps identifier to user_id
101
- or user_info.get("sub")
100
+ user_info.get("sub")
102
101
  or user_info.get("client_id")
103
102
  or user_info.get("username")
104
103
  or user_info.get("oid")
@@ -108,6 +107,7 @@ def _extract_user_identifier(user_info: dict) -> str:
108
107
  or user_info.get("email")
109
108
  or user_info.get("name")
110
109
  or user_info.get("azp")
110
+ or user_info.get("user_id") # internal /user_info endpoint format maps identifier to user_id
111
111
  )
112
112
 
113
113
  if user_identifier and user_identifier.lower() == "unknown":
@@ -209,6 +209,7 @@ def _create_auth_middleware(component):
209
209
  skip_paths = [
210
210
  "/api/v1/config",
211
211
  "/api/v1/auth/callback",
212
+ "/api/v1/auth/tool/callback",
212
213
  "/api/v1/auth/login",
213
214
  "/api/v1/auth/refresh",
214
215
  "/api/v1/csrf-token",
@@ -526,14 +527,14 @@ def setup_dependencies(component: "WebUIBackendComponent", database_url: str = N
526
527
  api_config_dict = _create_api_config(app_config, database_url)
527
528
 
528
529
  dependencies.set_api_config(api_config_dict)
529
- log.info("API configuration extracted and stored.")
530
+ log.debug("API configuration extracted and stored.")
530
531
 
531
532
  _setup_middleware(component)
532
533
  _setup_routers()
533
534
  _setup_static_files()
534
535
 
535
536
  _dependencies_initialized = True
536
- log.info("[setup_dependencies] Dependencies initialization complete")
537
+ log.debug("[setup_dependencies] Dependencies initialization complete")
537
538
 
538
539
 
539
540
  def _setup_middleware(component: "WebUIBackendComponent") -> None:
@@ -33,7 +33,7 @@ async def get_discovered_agent_cards(
33
33
  if agent_registry.get_agent(name)
34
34
  ]
35
35
 
36
- log.info("%sReturning %d discovered agent cards.", log_prefix, len(agents))
36
+ log.debug("%sReturning %d discovered agent cards.", log_prefix, len(agents))
37
37
  return agents
38
38
  except Exception as e:
39
39
  log.exception("%sError retrieving discovered agent cards: %s", log_prefix, e)
@@ -3,19 +3,20 @@ Router for handling authentication-related endpoints.
3
3
  """
4
4
 
5
5
  import logging
6
+ import secrets
7
+ from urllib.parse import urlencode
8
+
9
+ import httpx
6
10
  from fastapi import (
7
11
  APIRouter,
8
- Request as FastAPIRequest,
9
12
  Depends,
10
13
  HTTPException,
14
+ Request as FastAPIRequest,
11
15
  Response,
12
16
  )
13
- from fastapi.responses import RedirectResponse
14
- import httpx
15
- import secrets
16
- from urllib.parse import urlencode
17
+ from fastapi.responses import HTMLResponse, RedirectResponse
17
18
 
18
- from ...http_sse.dependencies import get_sac_component, get_api_config
19
+ from ...http_sse.dependencies import get_api_config, get_sac_component
19
20
 
20
21
  log = logging.getLogger(__name__)
21
22
 
@@ -212,3 +213,99 @@ async def refresh_token(
212
213
  "access_token": access_token,
213
214
  "refresh_token": new_refresh_token,
214
215
  }
216
+
217
+
218
+ @router.get("/auth/tool/callback")
219
+ async def auth_tool_callback(
220
+ request: FastAPIRequest,
221
+ component: "WebUIBackendComponent" = Depends(get_sac_component),
222
+ ):
223
+ """
224
+ Handles OAuth2 authorization code grant response for tool authentication.
225
+ """
226
+ code = request.query_params.get("code")
227
+ state = request.query_params.get("state")
228
+ error = request.query_params.get("error")
229
+ error_description = request.query_params.get("error_description")
230
+
231
+ if error:
232
+ log.error(f"OAuth2 tool callback received error: {error} - {error_description}")
233
+ return HTMLResponse(
234
+ content=f"""
235
+ <html>
236
+ <head>
237
+ <title>Authorization Error</title>
238
+ </head>
239
+ <body>
240
+ <h2>Authorization Error</h2>
241
+ <p>Error: {error}</p>
242
+ <p>Description: {error_description or 'No description provided'}</p>
243
+ <p>Please close this window and try again.</p>
244
+ </body>
245
+ </html>
246
+ """,
247
+ status_code=400
248
+ )
249
+
250
+ # Get the current request URL for logging/debugging
251
+ url = str(request.url)
252
+
253
+
254
+ if not code:
255
+ log.warning("OAuth2 tool callback received without authorization code")
256
+ return HTMLResponse(
257
+ content="""
258
+ <html>
259
+ <head>
260
+ <title>Authorization Error</title>
261
+ </head>
262
+ <body>
263
+ <h2>Authorization Error</h2>
264
+ <p>No authorization code received. Please close this window and try again.</p>
265
+ </body>
266
+ </html>
267
+ """,
268
+ status_code=400
269
+ )
270
+
271
+ log.info(f"OAuth2 tool callback received authorization code: {code}")
272
+
273
+ try:
274
+ from solace_agent_mesh_enterprise.auth.input_required import process_auth_grant_response
275
+ await process_auth_grant_response(component, code, state, url)
276
+ except ImportError:
277
+ pass
278
+
279
+ # Return simple HTML page instructing user to close the window
280
+ return HTMLResponse(
281
+ content="""
282
+ <html>
283
+ <head>
284
+ <title>Authorization Complete</title>
285
+ <style>
286
+ body {
287
+ font-family: Arial, sans-serif;
288
+ text-align: center;
289
+ padding: 50px;
290
+ background-color: #f5f5f5;
291
+ }
292
+ .container {
293
+ background: white;
294
+ padding: 30px;
295
+ border-radius: 8px;
296
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
297
+ display: inline-block;
298
+ }
299
+ h2 { color: #28a745; }
300
+ </style>
301
+ </head>
302
+ <body>
303
+ <div class="container">
304
+ <h2>✓ Authorization Complete</h2>
305
+ <p>You have successfully authorized the tool access.</p>
306
+ <p><strong>Please close this window.</strong></p>
307
+ </div>
308
+ </body>
309
+ </html>
310
+ """
311
+ )
@@ -69,7 +69,7 @@ async def get_app_config(
69
69
  "frontend_feature_enablement": feature_enablement,
70
70
  "persistence_enabled": api_config.get("persistence_enabled", False),
71
71
  }
72
- log.info("%sReturning frontend configuration.", log_prefix)
72
+ log.debug("%sReturning frontend configuration.", log_prefix)
73
73
  return config_data
74
74
  except Exception as e:
75
75
  log.exception(
@@ -129,7 +129,7 @@ async def save_task(
129
129
  Creates a new task or updates an existing one.
130
130
  """
131
131
  user_id = user.get("id")
132
- log.info(
132
+ log.debug(
133
133
  "User %s attempting to save task %s for session %s",
134
134
  user_id,
135
135
  request.task_id,