solace-agent-mesh 1.6.1__py3-none-any.whl → 1.6.3__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.
- solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
- solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +1 -1
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +135 -31
- solace_agent_mesh/agent/adk/models/lite_llm.py +5 -0
- solace_agent_mesh/agent/adk/runner.py +10 -12
- solace_agent_mesh/agent/adk/services.py +53 -17
- solace_agent_mesh/agent/adk/setup.py +66 -38
- solace_agent_mesh/agent/protocol/event_handlers.py +243 -122
- solace_agent_mesh/agent/proxies/a2a/app.py +3 -2
- solace_agent_mesh/agent/proxies/base/app.py +3 -2
- solace_agent_mesh/agent/sac/app.py +43 -2
- solace_agent_mesh/agent/sac/component.py +200 -72
- solace_agent_mesh/agent/sac/task_execution_context.py +35 -4
- solace_agent_mesh/agent/tools/tool_config_types.py +3 -0
- solace_agent_mesh/agent/utils/artifact_helpers.py +1 -1
- solace_agent_mesh/assets/docs/404.html +3 -3
- solace_agent_mesh/assets/docs/assets/js/240a0364.c39f8388.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/631738c7.7c4594c9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/66d4869e.830d443f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/71da7b71.ddbdfbe2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/94e8668d.3b883666.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e92d0134.4f395c6b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.720d2ef2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.ed05b14d.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.a8a75e0b.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +4 -25
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +76 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +5 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +23 -28
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +3 -6
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +3 -3
- solace_agent_mesh/assets/docs/lunr-index-1761744323675.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1761744323675.json +1 -0
- solace_agent_mesh/assets/docs/search-doc.json +1 -1
- solace_agent_mesh/assets/docs/sitemap.xml +1 -1
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-BTf6dqwp.js → authCallback-D4_RMYRh.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/{client-CaY59VuC.js → client-UZ3qU6Bq.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main--3yJYl7S.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-DojKHS49.js +342 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BEmvJSYz.js → vendor-DSqhjwq_.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
- solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
- solace_agent_mesh/common/a2a/events.py +2 -1
- solace_agent_mesh/common/sac/sam_component_base.py +24 -18
- solace_agent_mesh/common/utils/pydantic_utils.py +90 -3
- solace_agent_mesh/gateway/base/component.py +12 -8
- solace_agent_mesh/gateway/http_sse/app.py +26 -0
- solace_agent_mesh/gateway/http_sse/component.py +158 -79
- solace_agent_mesh/gateway/http_sse/dependencies.py +83 -59
- solace_agent_mesh/gateway/http_sse/main.py +35 -11
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/auth.py +103 -6
- solace_agent_mesh/gateway/http_sse/routers/config.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/sse.py +15 -5
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +3 -3
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +90 -8
- solace_agent_mesh/gateway/http_sse/services/session_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/session_manager.py +15 -15
- solace_agent_mesh/gateway/http_sse/shared/exception_handlers.py +16 -1
- solace_agent_mesh/gateway/http_sse/sse_manager.py +15 -6
- solace_agent_mesh/templates/logging_config_template.ini +2 -2
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.6.3.dist-info}/METADATA +2 -2
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.6.3.dist-info}/RECORD +112 -110
- solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.b12eac43.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.e268214e.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1761248203150.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1761248203150.json +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-B32noGmR.js +0 -342
- solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +0 -1
- /solace_agent_mesh/assets/docs/assets/js/{main.b12eac43.js.LICENSE.txt → main.ed05b14d.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.6.3.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.6.3.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.6.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Custom Solace AI Connector Component to host the FastAPI backend for the Web UI.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import logging
|
|
6
5
|
import asyncio
|
|
7
6
|
import json
|
|
7
|
+
import logging
|
|
8
8
|
import queue
|
|
9
9
|
import re
|
|
10
10
|
import threading
|
|
@@ -15,22 +15,20 @@ from typing import Any
|
|
|
15
15
|
import uvicorn
|
|
16
16
|
from fastapi import FastAPI, UploadFile
|
|
17
17
|
from fastapi import Request as FastAPIRequest
|
|
18
|
-
|
|
18
|
+
from solace_ai_connector.common.event import Event, EventType
|
|
19
19
|
from solace_ai_connector.components.inputs_outputs.broker_input import BrokerInput
|
|
20
20
|
from solace_ai_connector.flow.app import App as SACApp
|
|
21
|
-
from solace_ai_connector.common.event import Event, EventType
|
|
22
21
|
|
|
23
22
|
from ...common.agent_registry import AgentRegistry
|
|
24
23
|
from ...core_a2a.service import CoreA2AService
|
|
25
24
|
from ...gateway.base.component import BaseGatewayComponent
|
|
26
25
|
from ...gateway.http_sse.session_manager import SessionManager
|
|
27
26
|
from ...gateway.http_sse.sse_manager import SSEManager
|
|
28
|
-
from .
|
|
27
|
+
from . import dependencies
|
|
29
28
|
from .components import VisualizationForwarderComponent
|
|
30
29
|
from .components.task_logger_forwarder import TaskLoggerForwarderComponent
|
|
31
|
-
from .services.feedback_service import FeedbackService
|
|
32
30
|
from .services.task_logger_service import TaskLoggerService
|
|
33
|
-
from . import
|
|
31
|
+
from .sse_event_buffer import SSEEventBuffer
|
|
34
32
|
|
|
35
33
|
log = logging.getLogger(__name__)
|
|
36
34
|
|
|
@@ -115,6 +113,7 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
115
113
|
self.ssl_keyfile = self.get_config("ssl_keyfile", "")
|
|
116
114
|
self.ssl_certfile = self.get_config("ssl_certfile", "")
|
|
117
115
|
self.ssl_keyfile_password = self.get_config("ssl_keyfile_password", "")
|
|
116
|
+
self.model_config = self.get_config("model", None)
|
|
118
117
|
|
|
119
118
|
log.info(
|
|
120
119
|
"%s WebUI-specific configuration retrieved (Host: %s, Port: %d).",
|
|
@@ -146,11 +145,14 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
146
145
|
timer_id=self._sse_cleanup_timer_id,
|
|
147
146
|
interval_ms=cleanup_interval_sec * 1000,
|
|
148
147
|
)
|
|
149
|
-
|
|
148
|
+
|
|
150
149
|
# Set up health check timer for agent registry
|
|
151
150
|
from ...common.constants import HEALTH_CHECK_INTERVAL_SECONDS
|
|
151
|
+
|
|
152
152
|
self.health_check_timer_id = f"agent_health_check_{self.gateway_id}"
|
|
153
|
-
health_check_interval_seconds = self.get_config(
|
|
153
|
+
health_check_interval_seconds = self.get_config(
|
|
154
|
+
"agent_health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS
|
|
155
|
+
)
|
|
154
156
|
if health_check_interval_seconds > 0:
|
|
155
157
|
log.info(
|
|
156
158
|
"%s Scheduling agent health check every %d seconds.",
|
|
@@ -181,8 +183,9 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
181
183
|
else:
|
|
182
184
|
# Memory storage or no explicit configuration - no persistence service needed
|
|
183
185
|
self.database_url = None
|
|
184
|
-
|
|
185
|
-
|
|
186
|
+
|
|
187
|
+
# Validate that features requiring runtime database persistence are not enabled without database
|
|
188
|
+
if self.database_url is None:
|
|
186
189
|
task_logging_config = self.get_config("task_logging", {})
|
|
187
190
|
if task_logging_config.get("enabled", False):
|
|
188
191
|
raise ValueError(
|
|
@@ -190,15 +193,17 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
190
193
|
"Either set session_service.type='sql' with a valid database_url, "
|
|
191
194
|
"or disable task_logging.enabled."
|
|
192
195
|
)
|
|
193
|
-
|
|
196
|
+
|
|
194
197
|
feedback_config = self.get_config("feedback_publishing", {})
|
|
195
198
|
if feedback_config.get("enabled", False):
|
|
196
199
|
log.warning(
|
|
197
200
|
"%s Feedback publishing is enabled but database persistence is not configured. "
|
|
198
201
|
"Feedback will only be published to the broker, not stored locally.",
|
|
199
|
-
self.log_identifier
|
|
202
|
+
self.log_identifier,
|
|
200
203
|
)
|
|
201
204
|
|
|
205
|
+
platform_config = self.get_config("platform_service", {})
|
|
206
|
+
self.platform_database_url = platform_config.get("database_url")
|
|
202
207
|
component_config = self.get_config("component_config", {})
|
|
203
208
|
app_config = component_config.get("app_config", {})
|
|
204
209
|
|
|
@@ -241,27 +246,35 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
241
246
|
self._data_retention_timer_id = None
|
|
242
247
|
data_retention_config = self.get_config("data_retention", {})
|
|
243
248
|
if data_retention_config.get("enabled", True):
|
|
244
|
-
log.info(
|
|
245
|
-
|
|
249
|
+
log.info(
|
|
250
|
+
"%s Data retention is enabled. Initializing service and timer...",
|
|
251
|
+
self.log_identifier,
|
|
252
|
+
)
|
|
253
|
+
|
|
246
254
|
# Import and initialize the DataRetentionService
|
|
247
255
|
from .services.data_retention_service import DataRetentionService
|
|
248
|
-
|
|
256
|
+
|
|
249
257
|
session_factory = None
|
|
250
258
|
if self.database_url:
|
|
251
259
|
# SessionLocal will be initialized later in setup_dependencies
|
|
252
260
|
# We'll pass a lambda that returns SessionLocal when called
|
|
253
|
-
session_factory =
|
|
254
|
-
|
|
261
|
+
session_factory = (
|
|
262
|
+
lambda: dependencies.SessionLocal()
|
|
263
|
+
if dependencies.SessionLocal
|
|
264
|
+
else None
|
|
265
|
+
)
|
|
266
|
+
|
|
255
267
|
self.data_retention_service = DataRetentionService(
|
|
256
|
-
session_factory=session_factory,
|
|
257
|
-
config=data_retention_config
|
|
268
|
+
session_factory=session_factory, config=data_retention_config
|
|
258
269
|
)
|
|
259
|
-
|
|
270
|
+
|
|
260
271
|
# Create and start the cleanup timer
|
|
261
|
-
cleanup_interval_hours = data_retention_config.get(
|
|
272
|
+
cleanup_interval_hours = data_retention_config.get(
|
|
273
|
+
"cleanup_interval_hours", 24
|
|
274
|
+
)
|
|
262
275
|
cleanup_interval_ms = cleanup_interval_hours * 60 * 60 * 1000
|
|
263
276
|
self._data_retention_timer_id = f"data_retention_cleanup_{self.gateway_id}"
|
|
264
|
-
|
|
277
|
+
|
|
265
278
|
self.add_timer(
|
|
266
279
|
delay_ms=cleanup_interval_ms,
|
|
267
280
|
timer_id=self._data_retention_timer_id,
|
|
@@ -274,14 +287,16 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
274
287
|
cleanup_interval_hours,
|
|
275
288
|
)
|
|
276
289
|
else:
|
|
277
|
-
log.info(
|
|
290
|
+
log.info(
|
|
291
|
+
"%s Data retention is disabled via configuration.", self.log_identifier
|
|
292
|
+
)
|
|
278
293
|
|
|
279
294
|
log.info("%s Web UI Backend Component initialized.", self.log_identifier)
|
|
280
295
|
|
|
281
296
|
def process_event(self, event: Event):
|
|
282
297
|
if event.event_type == EventType.TIMER:
|
|
283
298
|
timer_id = event.data.get("timer_id")
|
|
284
|
-
|
|
299
|
+
|
|
285
300
|
if timer_id == self._sse_cleanup_timer_id:
|
|
286
301
|
log.debug("%s SSE buffer cleanup timer triggered.", self.log_identifier)
|
|
287
302
|
self.sse_event_buffer.cleanup_stale_buffers()
|
|
@@ -290,9 +305,11 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
290
305
|
log.debug("%s Agent health check timer triggered.", self.log_identifier)
|
|
291
306
|
self._check_agent_health()
|
|
292
307
|
return
|
|
293
|
-
|
|
308
|
+
|
|
294
309
|
if timer_id == self._data_retention_timer_id:
|
|
295
|
-
log.debug(
|
|
310
|
+
log.debug(
|
|
311
|
+
"%s Data retention cleanup timer triggered.", self.log_identifier
|
|
312
|
+
)
|
|
296
313
|
if self.data_retention_service:
|
|
297
314
|
try:
|
|
298
315
|
self.data_retention_service.cleanup_old_data()
|
|
@@ -386,7 +403,9 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
386
403
|
forwarder_cfg = {
|
|
387
404
|
"component_class": VisualizationForwarderComponent,
|
|
388
405
|
"component_name": f"{self.gateway_id}_viz_forwarder",
|
|
389
|
-
"component_config": {
|
|
406
|
+
"component_config": {
|
|
407
|
+
"target_queue_ref": self._visualization_message_queue
|
|
408
|
+
},
|
|
390
409
|
}
|
|
391
410
|
|
|
392
411
|
flow_config = {
|
|
@@ -437,7 +456,7 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
437
456
|
raise RuntimeError(
|
|
438
457
|
"Visualization flow setup error: BrokerInput not found."
|
|
439
458
|
)
|
|
440
|
-
log.
|
|
459
|
+
log.debug(
|
|
441
460
|
"%s Obtained reference to internal BrokerInput component.",
|
|
442
461
|
log_id_prefix,
|
|
443
462
|
)
|
|
@@ -883,7 +902,7 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
883
902
|
Manages global subscription reference counts.
|
|
884
903
|
"""
|
|
885
904
|
log_id_prefix = f"{self.log_identifier}[AddVizSub:{stream_id}]"
|
|
886
|
-
log.
|
|
905
|
+
log.debug(
|
|
887
906
|
"%s Attempting to add subscription to topic: %s", log_id_prefix, topic_str
|
|
888
907
|
)
|
|
889
908
|
|
|
@@ -1164,7 +1183,12 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1164
1183
|
log_id_prefix,
|
|
1165
1184
|
username,
|
|
1166
1185
|
)
|
|
1167
|
-
return {
|
|
1186
|
+
return {
|
|
1187
|
+
"id": username,
|
|
1188
|
+
"name": username,
|
|
1189
|
+
"email": username,
|
|
1190
|
+
"user_info": user_info,
|
|
1191
|
+
}
|
|
1168
1192
|
|
|
1169
1193
|
log.debug(
|
|
1170
1194
|
"%s No authenticated user in request.state, falling back to SessionManager.",
|
|
@@ -1198,7 +1222,7 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1198
1222
|
|
|
1199
1223
|
self.fastapi_app = fastapi_app_instance
|
|
1200
1224
|
|
|
1201
|
-
setup_dependencies(self, self.database_url)
|
|
1225
|
+
setup_dependencies(self, self.database_url, self.platform_database_url)
|
|
1202
1226
|
|
|
1203
1227
|
# Instantiate services that depend on the database session factory.
|
|
1204
1228
|
# This must be done *after* setup_dependencies has run.
|
|
@@ -1207,7 +1231,7 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1207
1231
|
self.task_logger_service = TaskLoggerService(
|
|
1208
1232
|
session_factory=session_factory, config=task_logging_config
|
|
1209
1233
|
)
|
|
1210
|
-
log.
|
|
1234
|
+
log.debug(
|
|
1211
1235
|
"%s Services dependent on database session factory have been initialized.",
|
|
1212
1236
|
self.log_identifier,
|
|
1213
1237
|
)
|
|
@@ -1238,14 +1262,14 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1238
1262
|
)
|
|
1239
1263
|
try:
|
|
1240
1264
|
self.fastapi_event_loop = asyncio.get_running_loop()
|
|
1241
|
-
log.
|
|
1265
|
+
log.debug(
|
|
1242
1266
|
"%s [_start_listener] Captured FastAPI event loop via startup event: %s",
|
|
1243
1267
|
self.log_identifier,
|
|
1244
1268
|
self.fastapi_event_loop,
|
|
1245
1269
|
)
|
|
1246
1270
|
|
|
1247
1271
|
if self.fastapi_event_loop:
|
|
1248
|
-
log.
|
|
1272
|
+
log.debug(
|
|
1249
1273
|
"%s Ensuring visualization flow is running...",
|
|
1250
1274
|
self.log_identifier,
|
|
1251
1275
|
)
|
|
@@ -1255,7 +1279,7 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1255
1279
|
self._visualization_processor_task is None
|
|
1256
1280
|
or self._visualization_processor_task.done()
|
|
1257
1281
|
):
|
|
1258
|
-
log.
|
|
1282
|
+
log.debug(
|
|
1259
1283
|
"%s Starting visualization message processor task.",
|
|
1260
1284
|
self.log_identifier,
|
|
1261
1285
|
)
|
|
@@ -1265,7 +1289,7 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1265
1289
|
)
|
|
1266
1290
|
)
|
|
1267
1291
|
else:
|
|
1268
|
-
log.
|
|
1292
|
+
log.debug(
|
|
1269
1293
|
"%s Visualization message processor task already running.",
|
|
1270
1294
|
self.log_identifier,
|
|
1271
1295
|
)
|
|
@@ -1297,7 +1321,9 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1297
1321
|
self.log_identifier,
|
|
1298
1322
|
)
|
|
1299
1323
|
else:
|
|
1300
|
-
log.info(
|
|
1324
|
+
log.info(
|
|
1325
|
+
"%s Task logging is disabled.", self.log_identifier
|
|
1326
|
+
)
|
|
1301
1327
|
else:
|
|
1302
1328
|
log.error(
|
|
1303
1329
|
"%s FastAPI event loop not captured. Cannot start visualization processor.",
|
|
@@ -1313,24 +1339,36 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1313
1339
|
self.stop_signal.set()
|
|
1314
1340
|
|
|
1315
1341
|
try:
|
|
1316
|
-
from solace_agent_mesh_enterprise.init_enterprise import
|
|
1317
|
-
|
|
1342
|
+
from solace_agent_mesh_enterprise.init_enterprise import (
|
|
1343
|
+
start_enterprise_background_tasks,
|
|
1344
|
+
)
|
|
1345
|
+
|
|
1346
|
+
log.info(
|
|
1347
|
+
"%s Starting enterprise background tasks...",
|
|
1348
|
+
self.log_identifier,
|
|
1349
|
+
)
|
|
1318
1350
|
await start_enterprise_background_tasks(self)
|
|
1319
|
-
log.info(
|
|
1351
|
+
log.info(
|
|
1352
|
+
"%s Enterprise background tasks started successfully",
|
|
1353
|
+
self.log_identifier,
|
|
1354
|
+
)
|
|
1320
1355
|
except ImportError:
|
|
1321
|
-
log.debug(
|
|
1356
|
+
log.debug(
|
|
1357
|
+
"%s Enterprise package not available - skipping background tasks",
|
|
1358
|
+
self.log_identifier,
|
|
1359
|
+
)
|
|
1322
1360
|
except RuntimeError as enterprise_err:
|
|
1323
1361
|
log.warning(
|
|
1324
1362
|
"%s Enterprise background tasks disabled: %s - Community features will continue normally",
|
|
1325
1363
|
self.log_identifier,
|
|
1326
|
-
enterprise_err
|
|
1364
|
+
enterprise_err,
|
|
1327
1365
|
)
|
|
1328
1366
|
except Exception as enterprise_err:
|
|
1329
1367
|
log.error(
|
|
1330
1368
|
"%s Failed to start enterprise background tasks: %s - Community features will continue normally",
|
|
1331
1369
|
self.log_identifier,
|
|
1332
1370
|
enterprise_err,
|
|
1333
|
-
exc_info=True
|
|
1371
|
+
exc_info=True,
|
|
1334
1372
|
)
|
|
1335
1373
|
|
|
1336
1374
|
@self.fastapi_app.on_event("shutdown")
|
|
@@ -1341,18 +1379,29 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1341
1379
|
)
|
|
1342
1380
|
|
|
1343
1381
|
try:
|
|
1344
|
-
from solace_agent_mesh_enterprise.init_enterprise import
|
|
1345
|
-
|
|
1382
|
+
from solace_agent_mesh_enterprise.init_enterprise import (
|
|
1383
|
+
stop_enterprise_background_tasks,
|
|
1384
|
+
)
|
|
1385
|
+
|
|
1386
|
+
log.info(
|
|
1387
|
+
"%s Stopping enterprise background tasks...",
|
|
1388
|
+
self.log_identifier,
|
|
1389
|
+
)
|
|
1346
1390
|
await stop_enterprise_background_tasks()
|
|
1347
|
-
log.info(
|
|
1391
|
+
log.info(
|
|
1392
|
+
"%s Enterprise background tasks stopped", self.log_identifier
|
|
1393
|
+
)
|
|
1348
1394
|
except ImportError:
|
|
1349
|
-
log.debug(
|
|
1395
|
+
log.debug(
|
|
1396
|
+
"%s Enterprise package not available - no background tasks to stop",
|
|
1397
|
+
self.log_identifier,
|
|
1398
|
+
)
|
|
1350
1399
|
except Exception as enterprise_err:
|
|
1351
1400
|
log.error(
|
|
1352
1401
|
"%s Failed to stop enterprise background tasks: %s",
|
|
1353
1402
|
self.log_identifier,
|
|
1354
1403
|
enterprise_err,
|
|
1355
|
-
exc_info=True
|
|
1404
|
+
exc_info=True,
|
|
1356
1405
|
)
|
|
1357
1406
|
|
|
1358
1407
|
self.fastapi_thread = threading.Thread(
|
|
@@ -1417,18 +1466,18 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1417
1466
|
def cleanup(self):
|
|
1418
1467
|
"""Gracefully shuts down the component and the FastAPI server."""
|
|
1419
1468
|
log.info("%s Cleaning up Web UI Backend Component...", self.log_identifier)
|
|
1420
|
-
|
|
1469
|
+
|
|
1421
1470
|
# Cancel timers
|
|
1422
1471
|
self.cancel_timer(self._sse_cleanup_timer_id)
|
|
1423
1472
|
if self._data_retention_timer_id:
|
|
1424
1473
|
self.cancel_timer(self._data_retention_timer_id)
|
|
1425
1474
|
log.info("%s Cancelled data retention cleanup timer.", self.log_identifier)
|
|
1426
|
-
|
|
1475
|
+
|
|
1427
1476
|
# Clean up data retention service
|
|
1428
1477
|
if self.data_retention_service:
|
|
1429
1478
|
self.data_retention_service = None
|
|
1430
1479
|
log.info("%s Data retention service cleaned up.", self.log_identifier)
|
|
1431
|
-
|
|
1480
|
+
|
|
1432
1481
|
self.cancel_timer(self.health_check_timer_id)
|
|
1433
1482
|
log.info("%s Cleaning up visualization resources...", self.log_identifier)
|
|
1434
1483
|
if self._visualization_message_queue:
|
|
@@ -1445,7 +1494,10 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1445
1494
|
)
|
|
1446
1495
|
self._visualization_processor_task.cancel()
|
|
1447
1496
|
|
|
1448
|
-
if
|
|
1497
|
+
if (
|
|
1498
|
+
self._task_logger_processor_task
|
|
1499
|
+
and not self._task_logger_processor_task.done()
|
|
1500
|
+
):
|
|
1449
1501
|
log.info("%s Cancelling task logger processor task...", self.log_identifier)
|
|
1450
1502
|
self._task_logger_processor_task.cancel()
|
|
1451
1503
|
|
|
@@ -1659,9 +1711,9 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1659
1711
|
(summary_str[:100] + "...") if len(summary_str) > 100 else summary_str
|
|
1660
1712
|
)
|
|
1661
1713
|
except Exception:
|
|
1662
|
-
details["payload_summary"][
|
|
1663
|
-
"
|
|
1664
|
-
|
|
1714
|
+
details["payload_summary"]["params_preview"] = (
|
|
1715
|
+
"[Could not serialize payload]"
|
|
1716
|
+
)
|
|
1665
1717
|
|
|
1666
1718
|
return details
|
|
1667
1719
|
|
|
@@ -1755,70 +1807,88 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1755
1807
|
|
|
1756
1808
|
def get_agent_registry(self) -> AgentRegistry:
|
|
1757
1809
|
return self.agent_registry
|
|
1758
|
-
|
|
1810
|
+
|
|
1759
1811
|
def _check_agent_health(self):
|
|
1760
1812
|
"""
|
|
1761
1813
|
Checks the health of peer agents and de-registers unresponsive ones.
|
|
1762
1814
|
This is called periodically by the health check timer.
|
|
1763
1815
|
Uses TTL-based expiration to determine if an agent is unresponsive.
|
|
1764
1816
|
"""
|
|
1765
|
-
|
|
1817
|
+
|
|
1766
1818
|
log.debug("%s Performing agent health check...", self.log_identifier)
|
|
1767
|
-
|
|
1819
|
+
|
|
1768
1820
|
# Get TTL from configuration or use default from constants
|
|
1769
|
-
from ...common.constants import
|
|
1770
|
-
|
|
1771
|
-
|
|
1821
|
+
from ...common.constants import (
|
|
1822
|
+
HEALTH_CHECK_INTERVAL_SECONDS,
|
|
1823
|
+
HEALTH_CHECK_TTL_SECONDS,
|
|
1824
|
+
)
|
|
1825
|
+
|
|
1826
|
+
ttl_seconds = self.get_config(
|
|
1827
|
+
"agent_health_check_ttl_seconds", HEALTH_CHECK_TTL_SECONDS
|
|
1828
|
+
)
|
|
1829
|
+
health_check_interval = self.get_config(
|
|
1830
|
+
"agent_health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS
|
|
1831
|
+
)
|
|
1772
1832
|
|
|
1773
1833
|
log.debug(
|
|
1774
1834
|
"%s Health check configuration: interval=%d seconds, TTL=%d seconds",
|
|
1775
1835
|
self.log_identifier,
|
|
1776
1836
|
health_check_interval,
|
|
1777
|
-
ttl_seconds
|
|
1837
|
+
ttl_seconds,
|
|
1778
1838
|
)
|
|
1779
|
-
|
|
1839
|
+
|
|
1780
1840
|
# Validate configuration values
|
|
1781
|
-
if
|
|
1841
|
+
if (
|
|
1842
|
+
ttl_seconds <= 0
|
|
1843
|
+
or health_check_interval <= 0
|
|
1844
|
+
or ttl_seconds < health_check_interval
|
|
1845
|
+
):
|
|
1782
1846
|
log.error(
|
|
1783
1847
|
"%s agent_health_check_ttl_seconds (%d) and agent_health_check_interval_seconds (%d) must be positive and TTL must be greater than interval.",
|
|
1784
1848
|
self.log_identifier,
|
|
1785
1849
|
ttl_seconds,
|
|
1786
|
-
health_check_interval
|
|
1850
|
+
health_check_interval,
|
|
1787
1851
|
)
|
|
1788
|
-
raise ValueError(
|
|
1789
|
-
|
|
1852
|
+
raise ValueError(
|
|
1853
|
+
f"Invalid health check configuration. agent_health_check_ttl_seconds ({ttl_seconds}) and agent_health_check_interval_seconds ({health_check_interval}) must be positive and TTL must be greater than interval."
|
|
1854
|
+
)
|
|
1855
|
+
|
|
1790
1856
|
# Get all agent names from the registry
|
|
1791
1857
|
agent_names = self.agent_registry.get_agent_names()
|
|
1792
1858
|
total_agents = len(agent_names)
|
|
1793
1859
|
agents_to_deregister = []
|
|
1794
|
-
|
|
1795
|
-
log.debug(
|
|
1796
|
-
|
|
1860
|
+
|
|
1861
|
+
log.debug(
|
|
1862
|
+
"%s Checking health of %d peer agents", self.log_identifier, total_agents
|
|
1863
|
+
)
|
|
1864
|
+
|
|
1797
1865
|
for agent_name in agent_names:
|
|
1798
1866
|
# Check if the agent's TTL has expired
|
|
1799
|
-
is_expired, time_since_last_seen = self.agent_registry.check_ttl_expired(
|
|
1800
|
-
|
|
1867
|
+
is_expired, time_since_last_seen = self.agent_registry.check_ttl_expired(
|
|
1868
|
+
agent_name, ttl_seconds
|
|
1869
|
+
)
|
|
1870
|
+
|
|
1801
1871
|
if is_expired:
|
|
1802
1872
|
log.warning(
|
|
1803
1873
|
"%s Agent '%s' TTL has expired. De-registering. Time since last seen: %d seconds (TTL: %d seconds)",
|
|
1804
1874
|
self.log_identifier,
|
|
1805
1875
|
agent_name,
|
|
1806
1876
|
time_since_last_seen,
|
|
1807
|
-
ttl_seconds
|
|
1877
|
+
ttl_seconds,
|
|
1808
1878
|
)
|
|
1809
1879
|
agents_to_deregister.append(agent_name)
|
|
1810
|
-
|
|
1880
|
+
|
|
1811
1881
|
# De-register unresponsive agents
|
|
1812
1882
|
for agent_name in agents_to_deregister:
|
|
1813
1883
|
self._deregister_agent(agent_name)
|
|
1814
|
-
|
|
1815
|
-
log.
|
|
1884
|
+
|
|
1885
|
+
log.debug(
|
|
1816
1886
|
"%s Agent health check completed. Total agents: %d, De-registered: %d",
|
|
1817
1887
|
self.log_identifier,
|
|
1818
1888
|
total_agents,
|
|
1819
|
-
len(agents_to_deregister)
|
|
1889
|
+
len(agents_to_deregister),
|
|
1820
1890
|
)
|
|
1821
|
-
|
|
1891
|
+
|
|
1822
1892
|
def _deregister_agent(self, agent_name: str):
|
|
1823
1893
|
"""
|
|
1824
1894
|
De-registers an agent from the registry and publishes a de-registration event.
|
|
@@ -2052,6 +2122,15 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
2052
2122
|
)
|
|
2053
2123
|
return
|
|
2054
2124
|
|
|
2125
|
+
try:
|
|
2126
|
+
from solace_agent_mesh_enterprise.auth.input_required import (
|
|
2127
|
+
handle_input_required_request,
|
|
2128
|
+
)
|
|
2129
|
+
|
|
2130
|
+
event_data = handle_input_required_request(event_data, sse_task_id, self)
|
|
2131
|
+
except ImportError:
|
|
2132
|
+
pass
|
|
2133
|
+
|
|
2055
2134
|
log.debug(
|
|
2056
2135
|
"%s Sending update for A2A Task ID %s to SSE Task ID %s. Final chunk: %s",
|
|
2057
2136
|
log_id_prefix,
|
|
@@ -2073,7 +2152,7 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
2073
2152
|
await self.sse_manager.send_event(
|
|
2074
2153
|
task_id=sse_task_id, event_data=sse_payload, event_type=sse_event_type
|
|
2075
2154
|
)
|
|
2076
|
-
log.
|
|
2155
|
+
log.debug(
|
|
2077
2156
|
"%s Successfully sent %s via SSE for A2A Task ID %s.",
|
|
2078
2157
|
log_id_prefix,
|
|
2079
2158
|
sse_event_type,
|