solace-agent-mesh 1.6.2__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/services.py +3 -3
- solace_agent_mesh/assets/docs/404.html +3 -3
- solace_agent_mesh/assets/docs/assets/js/94e8668d.3b883666.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{main.d1643f0b.js → main.ed05b14d.js} +2 -2
- solace_agent_mesh/assets/docs/assets/js/{runtime~main.97f920d4.js → runtime~main.a8a75e0b.js} +1 -1
- 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 +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +3 -3
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +3 -3
- 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 -3
- 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/cli/__init__.py +1 -1
- solace_agent_mesh/gateway/http_sse/app.py +19 -0
- solace_agent_mesh/gateway/http_sse/component.py +143 -72
- solace_agent_mesh/gateway/http_sse/main.py +32 -9
- {solace_agent_mesh-1.6.2.dist-info → solace_agent_mesh-1.6.3.dist-info}/METADATA +1 -1
- {solace_agent_mesh-1.6.2.dist-info → solace_agent_mesh-1.6.3.dist-info}/RECORD +67 -67
- solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1761663789856.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1761663789856.json +0 -1
- /solace_agent_mesh/assets/docs/assets/js/{main.d1643f0b.js.LICENSE.txt → main.ed05b14d.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.6.2.dist-info → solace_agent_mesh-1.6.3.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.6.2.dist-info → solace_agent_mesh-1.6.3.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.6.2.dist-info → solace_agent_mesh-1.6.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.6.
|
|
1
|
+
__version__ = "1.6.3"
|
|
@@ -202,6 +202,25 @@ class WebUIBackendApp(BaseGatewayApp):
|
|
|
202
202
|
},
|
|
203
203
|
},
|
|
204
204
|
},
|
|
205
|
+
{
|
|
206
|
+
"name": "platform_service",
|
|
207
|
+
"required": False,
|
|
208
|
+
"type": "dict",
|
|
209
|
+
"default": {},
|
|
210
|
+
"description": "Configuration for the Platform Service (enterprise features: agents, connectors, deployments).",
|
|
211
|
+
"dict_schema": {
|
|
212
|
+
"database_url": {
|
|
213
|
+
"type": "string",
|
|
214
|
+
"required": False,
|
|
215
|
+
"default": None,
|
|
216
|
+
"description": (
|
|
217
|
+
"Database URL for platform data (agents, connectors, deployments). "
|
|
218
|
+
"REQUIRED for platform features to be available. "
|
|
219
|
+
"Example: postgresql://user:pass@host:5432/platform_db"
|
|
220
|
+
),
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
},
|
|
205
224
|
{
|
|
206
225
|
"name": "task_logging",
|
|
207
226
|
"required": False,
|
|
@@ -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
|
|
|
@@ -147,11 +145,14 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
147
145
|
timer_id=self._sse_cleanup_timer_id,
|
|
148
146
|
interval_ms=cleanup_interval_sec * 1000,
|
|
149
147
|
)
|
|
150
|
-
|
|
148
|
+
|
|
151
149
|
# Set up health check timer for agent registry
|
|
152
150
|
from ...common.constants import HEALTH_CHECK_INTERVAL_SECONDS
|
|
151
|
+
|
|
153
152
|
self.health_check_timer_id = f"agent_health_check_{self.gateway_id}"
|
|
154
|
-
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
|
+
)
|
|
155
156
|
if health_check_interval_seconds > 0:
|
|
156
157
|
log.info(
|
|
157
158
|
"%s Scheduling agent health check every %d seconds.",
|
|
@@ -182,8 +183,9 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
182
183
|
else:
|
|
183
184
|
# Memory storage or no explicit configuration - no persistence service needed
|
|
184
185
|
self.database_url = None
|
|
185
|
-
|
|
186
|
-
|
|
186
|
+
|
|
187
|
+
# Validate that features requiring runtime database persistence are not enabled without database
|
|
188
|
+
if self.database_url is None:
|
|
187
189
|
task_logging_config = self.get_config("task_logging", {})
|
|
188
190
|
if task_logging_config.get("enabled", False):
|
|
189
191
|
raise ValueError(
|
|
@@ -191,15 +193,17 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
191
193
|
"Either set session_service.type='sql' with a valid database_url, "
|
|
192
194
|
"or disable task_logging.enabled."
|
|
193
195
|
)
|
|
194
|
-
|
|
196
|
+
|
|
195
197
|
feedback_config = self.get_config("feedback_publishing", {})
|
|
196
198
|
if feedback_config.get("enabled", False):
|
|
197
199
|
log.warning(
|
|
198
200
|
"%s Feedback publishing is enabled but database persistence is not configured. "
|
|
199
201
|
"Feedback will only be published to the broker, not stored locally.",
|
|
200
|
-
self.log_identifier
|
|
202
|
+
self.log_identifier,
|
|
201
203
|
)
|
|
202
204
|
|
|
205
|
+
platform_config = self.get_config("platform_service", {})
|
|
206
|
+
self.platform_database_url = platform_config.get("database_url")
|
|
203
207
|
component_config = self.get_config("component_config", {})
|
|
204
208
|
app_config = component_config.get("app_config", {})
|
|
205
209
|
|
|
@@ -242,27 +246,35 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
242
246
|
self._data_retention_timer_id = None
|
|
243
247
|
data_retention_config = self.get_config("data_retention", {})
|
|
244
248
|
if data_retention_config.get("enabled", True):
|
|
245
|
-
log.info(
|
|
246
|
-
|
|
249
|
+
log.info(
|
|
250
|
+
"%s Data retention is enabled. Initializing service and timer...",
|
|
251
|
+
self.log_identifier,
|
|
252
|
+
)
|
|
253
|
+
|
|
247
254
|
# Import and initialize the DataRetentionService
|
|
248
255
|
from .services.data_retention_service import DataRetentionService
|
|
249
|
-
|
|
256
|
+
|
|
250
257
|
session_factory = None
|
|
251
258
|
if self.database_url:
|
|
252
259
|
# SessionLocal will be initialized later in setup_dependencies
|
|
253
260
|
# We'll pass a lambda that returns SessionLocal when called
|
|
254
|
-
session_factory =
|
|
255
|
-
|
|
261
|
+
session_factory = (
|
|
262
|
+
lambda: dependencies.SessionLocal()
|
|
263
|
+
if dependencies.SessionLocal
|
|
264
|
+
else None
|
|
265
|
+
)
|
|
266
|
+
|
|
256
267
|
self.data_retention_service = DataRetentionService(
|
|
257
|
-
session_factory=session_factory,
|
|
258
|
-
config=data_retention_config
|
|
268
|
+
session_factory=session_factory, config=data_retention_config
|
|
259
269
|
)
|
|
260
|
-
|
|
270
|
+
|
|
261
271
|
# Create and start the cleanup timer
|
|
262
|
-
cleanup_interval_hours = data_retention_config.get(
|
|
272
|
+
cleanup_interval_hours = data_retention_config.get(
|
|
273
|
+
"cleanup_interval_hours", 24
|
|
274
|
+
)
|
|
263
275
|
cleanup_interval_ms = cleanup_interval_hours * 60 * 60 * 1000
|
|
264
276
|
self._data_retention_timer_id = f"data_retention_cleanup_{self.gateway_id}"
|
|
265
|
-
|
|
277
|
+
|
|
266
278
|
self.add_timer(
|
|
267
279
|
delay_ms=cleanup_interval_ms,
|
|
268
280
|
timer_id=self._data_retention_timer_id,
|
|
@@ -275,14 +287,16 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
275
287
|
cleanup_interval_hours,
|
|
276
288
|
)
|
|
277
289
|
else:
|
|
278
|
-
log.info(
|
|
290
|
+
log.info(
|
|
291
|
+
"%s Data retention is disabled via configuration.", self.log_identifier
|
|
292
|
+
)
|
|
279
293
|
|
|
280
294
|
log.info("%s Web UI Backend Component initialized.", self.log_identifier)
|
|
281
295
|
|
|
282
296
|
def process_event(self, event: Event):
|
|
283
297
|
if event.event_type == EventType.TIMER:
|
|
284
298
|
timer_id = event.data.get("timer_id")
|
|
285
|
-
|
|
299
|
+
|
|
286
300
|
if timer_id == self._sse_cleanup_timer_id:
|
|
287
301
|
log.debug("%s SSE buffer cleanup timer triggered.", self.log_identifier)
|
|
288
302
|
self.sse_event_buffer.cleanup_stale_buffers()
|
|
@@ -291,9 +305,11 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
291
305
|
log.debug("%s Agent health check timer triggered.", self.log_identifier)
|
|
292
306
|
self._check_agent_health()
|
|
293
307
|
return
|
|
294
|
-
|
|
308
|
+
|
|
295
309
|
if timer_id == self._data_retention_timer_id:
|
|
296
|
-
log.debug(
|
|
310
|
+
log.debug(
|
|
311
|
+
"%s Data retention cleanup timer triggered.", self.log_identifier
|
|
312
|
+
)
|
|
297
313
|
if self.data_retention_service:
|
|
298
314
|
try:
|
|
299
315
|
self.data_retention_service.cleanup_old_data()
|
|
@@ -387,7 +403,9 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
387
403
|
forwarder_cfg = {
|
|
388
404
|
"component_class": VisualizationForwarderComponent,
|
|
389
405
|
"component_name": f"{self.gateway_id}_viz_forwarder",
|
|
390
|
-
"component_config": {
|
|
406
|
+
"component_config": {
|
|
407
|
+
"target_queue_ref": self._visualization_message_queue
|
|
408
|
+
},
|
|
391
409
|
}
|
|
392
410
|
|
|
393
411
|
flow_config = {
|
|
@@ -1165,7 +1183,12 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1165
1183
|
log_id_prefix,
|
|
1166
1184
|
username,
|
|
1167
1185
|
)
|
|
1168
|
-
return {
|
|
1186
|
+
return {
|
|
1187
|
+
"id": username,
|
|
1188
|
+
"name": username,
|
|
1189
|
+
"email": username,
|
|
1190
|
+
"user_info": user_info,
|
|
1191
|
+
}
|
|
1169
1192
|
|
|
1170
1193
|
log.debug(
|
|
1171
1194
|
"%s No authenticated user in request.state, falling back to SessionManager.",
|
|
@@ -1199,7 +1222,7 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1199
1222
|
|
|
1200
1223
|
self.fastapi_app = fastapi_app_instance
|
|
1201
1224
|
|
|
1202
|
-
setup_dependencies(self, self.database_url)
|
|
1225
|
+
setup_dependencies(self, self.database_url, self.platform_database_url)
|
|
1203
1226
|
|
|
1204
1227
|
# Instantiate services that depend on the database session factory.
|
|
1205
1228
|
# This must be done *after* setup_dependencies has run.
|
|
@@ -1298,7 +1321,9 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1298
1321
|
self.log_identifier,
|
|
1299
1322
|
)
|
|
1300
1323
|
else:
|
|
1301
|
-
log.info(
|
|
1324
|
+
log.info(
|
|
1325
|
+
"%s Task logging is disabled.", self.log_identifier
|
|
1326
|
+
)
|
|
1302
1327
|
else:
|
|
1303
1328
|
log.error(
|
|
1304
1329
|
"%s FastAPI event loop not captured. Cannot start visualization processor.",
|
|
@@ -1314,24 +1339,36 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1314
1339
|
self.stop_signal.set()
|
|
1315
1340
|
|
|
1316
1341
|
try:
|
|
1317
|
-
from solace_agent_mesh_enterprise.init_enterprise import
|
|
1318
|
-
|
|
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
|
+
)
|
|
1319
1350
|
await start_enterprise_background_tasks(self)
|
|
1320
|
-
log.info(
|
|
1351
|
+
log.info(
|
|
1352
|
+
"%s Enterprise background tasks started successfully",
|
|
1353
|
+
self.log_identifier,
|
|
1354
|
+
)
|
|
1321
1355
|
except ImportError:
|
|
1322
|
-
log.debug(
|
|
1356
|
+
log.debug(
|
|
1357
|
+
"%s Enterprise package not available - skipping background tasks",
|
|
1358
|
+
self.log_identifier,
|
|
1359
|
+
)
|
|
1323
1360
|
except RuntimeError as enterprise_err:
|
|
1324
1361
|
log.warning(
|
|
1325
1362
|
"%s Enterprise background tasks disabled: %s - Community features will continue normally",
|
|
1326
1363
|
self.log_identifier,
|
|
1327
|
-
enterprise_err
|
|
1364
|
+
enterprise_err,
|
|
1328
1365
|
)
|
|
1329
1366
|
except Exception as enterprise_err:
|
|
1330
1367
|
log.error(
|
|
1331
1368
|
"%s Failed to start enterprise background tasks: %s - Community features will continue normally",
|
|
1332
1369
|
self.log_identifier,
|
|
1333
1370
|
enterprise_err,
|
|
1334
|
-
exc_info=True
|
|
1371
|
+
exc_info=True,
|
|
1335
1372
|
)
|
|
1336
1373
|
|
|
1337
1374
|
@self.fastapi_app.on_event("shutdown")
|
|
@@ -1342,18 +1379,29 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1342
1379
|
)
|
|
1343
1380
|
|
|
1344
1381
|
try:
|
|
1345
|
-
from solace_agent_mesh_enterprise.init_enterprise import
|
|
1346
|
-
|
|
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
|
+
)
|
|
1347
1390
|
await stop_enterprise_background_tasks()
|
|
1348
|
-
log.info(
|
|
1391
|
+
log.info(
|
|
1392
|
+
"%s Enterprise background tasks stopped", self.log_identifier
|
|
1393
|
+
)
|
|
1349
1394
|
except ImportError:
|
|
1350
|
-
log.debug(
|
|
1395
|
+
log.debug(
|
|
1396
|
+
"%s Enterprise package not available - no background tasks to stop",
|
|
1397
|
+
self.log_identifier,
|
|
1398
|
+
)
|
|
1351
1399
|
except Exception as enterprise_err:
|
|
1352
1400
|
log.error(
|
|
1353
1401
|
"%s Failed to stop enterprise background tasks: %s",
|
|
1354
1402
|
self.log_identifier,
|
|
1355
1403
|
enterprise_err,
|
|
1356
|
-
exc_info=True
|
|
1404
|
+
exc_info=True,
|
|
1357
1405
|
)
|
|
1358
1406
|
|
|
1359
1407
|
self.fastapi_thread = threading.Thread(
|
|
@@ -1418,18 +1466,18 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1418
1466
|
def cleanup(self):
|
|
1419
1467
|
"""Gracefully shuts down the component and the FastAPI server."""
|
|
1420
1468
|
log.info("%s Cleaning up Web UI Backend Component...", self.log_identifier)
|
|
1421
|
-
|
|
1469
|
+
|
|
1422
1470
|
# Cancel timers
|
|
1423
1471
|
self.cancel_timer(self._sse_cleanup_timer_id)
|
|
1424
1472
|
if self._data_retention_timer_id:
|
|
1425
1473
|
self.cancel_timer(self._data_retention_timer_id)
|
|
1426
1474
|
log.info("%s Cancelled data retention cleanup timer.", self.log_identifier)
|
|
1427
|
-
|
|
1475
|
+
|
|
1428
1476
|
# Clean up data retention service
|
|
1429
1477
|
if self.data_retention_service:
|
|
1430
1478
|
self.data_retention_service = None
|
|
1431
1479
|
log.info("%s Data retention service cleaned up.", self.log_identifier)
|
|
1432
|
-
|
|
1480
|
+
|
|
1433
1481
|
self.cancel_timer(self.health_check_timer_id)
|
|
1434
1482
|
log.info("%s Cleaning up visualization resources...", self.log_identifier)
|
|
1435
1483
|
if self._visualization_message_queue:
|
|
@@ -1446,7 +1494,10 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1446
1494
|
)
|
|
1447
1495
|
self._visualization_processor_task.cancel()
|
|
1448
1496
|
|
|
1449
|
-
if
|
|
1497
|
+
if (
|
|
1498
|
+
self._task_logger_processor_task
|
|
1499
|
+
and not self._task_logger_processor_task.done()
|
|
1500
|
+
):
|
|
1450
1501
|
log.info("%s Cancelling task logger processor task...", self.log_identifier)
|
|
1451
1502
|
self._task_logger_processor_task.cancel()
|
|
1452
1503
|
|
|
@@ -1660,9 +1711,9 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1660
1711
|
(summary_str[:100] + "...") if len(summary_str) > 100 else summary_str
|
|
1661
1712
|
)
|
|
1662
1713
|
except Exception:
|
|
1663
|
-
details["payload_summary"][
|
|
1664
|
-
"
|
|
1665
|
-
|
|
1714
|
+
details["payload_summary"]["params_preview"] = (
|
|
1715
|
+
"[Could not serialize payload]"
|
|
1716
|
+
)
|
|
1666
1717
|
|
|
1667
1718
|
return details
|
|
1668
1719
|
|
|
@@ -1756,70 +1807,88 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
1756
1807
|
|
|
1757
1808
|
def get_agent_registry(self) -> AgentRegistry:
|
|
1758
1809
|
return self.agent_registry
|
|
1759
|
-
|
|
1810
|
+
|
|
1760
1811
|
def _check_agent_health(self):
|
|
1761
1812
|
"""
|
|
1762
1813
|
Checks the health of peer agents and de-registers unresponsive ones.
|
|
1763
1814
|
This is called periodically by the health check timer.
|
|
1764
1815
|
Uses TTL-based expiration to determine if an agent is unresponsive.
|
|
1765
1816
|
"""
|
|
1766
|
-
|
|
1817
|
+
|
|
1767
1818
|
log.debug("%s Performing agent health check...", self.log_identifier)
|
|
1768
|
-
|
|
1819
|
+
|
|
1769
1820
|
# Get TTL from configuration or use default from constants
|
|
1770
|
-
from ...common.constants import
|
|
1771
|
-
|
|
1772
|
-
|
|
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
|
+
)
|
|
1773
1832
|
|
|
1774
1833
|
log.debug(
|
|
1775
1834
|
"%s Health check configuration: interval=%d seconds, TTL=%d seconds",
|
|
1776
1835
|
self.log_identifier,
|
|
1777
1836
|
health_check_interval,
|
|
1778
|
-
ttl_seconds
|
|
1837
|
+
ttl_seconds,
|
|
1779
1838
|
)
|
|
1780
|
-
|
|
1839
|
+
|
|
1781
1840
|
# Validate configuration values
|
|
1782
|
-
if
|
|
1841
|
+
if (
|
|
1842
|
+
ttl_seconds <= 0
|
|
1843
|
+
or health_check_interval <= 0
|
|
1844
|
+
or ttl_seconds < health_check_interval
|
|
1845
|
+
):
|
|
1783
1846
|
log.error(
|
|
1784
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.",
|
|
1785
1848
|
self.log_identifier,
|
|
1786
1849
|
ttl_seconds,
|
|
1787
|
-
health_check_interval
|
|
1850
|
+
health_check_interval,
|
|
1851
|
+
)
|
|
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."
|
|
1788
1854
|
)
|
|
1789
|
-
|
|
1790
|
-
|
|
1855
|
+
|
|
1791
1856
|
# Get all agent names from the registry
|
|
1792
1857
|
agent_names = self.agent_registry.get_agent_names()
|
|
1793
1858
|
total_agents = len(agent_names)
|
|
1794
1859
|
agents_to_deregister = []
|
|
1795
|
-
|
|
1796
|
-
log.debug(
|
|
1797
|
-
|
|
1860
|
+
|
|
1861
|
+
log.debug(
|
|
1862
|
+
"%s Checking health of %d peer agents", self.log_identifier, total_agents
|
|
1863
|
+
)
|
|
1864
|
+
|
|
1798
1865
|
for agent_name in agent_names:
|
|
1799
1866
|
# Check if the agent's TTL has expired
|
|
1800
|
-
is_expired, time_since_last_seen = self.agent_registry.check_ttl_expired(
|
|
1801
|
-
|
|
1867
|
+
is_expired, time_since_last_seen = self.agent_registry.check_ttl_expired(
|
|
1868
|
+
agent_name, ttl_seconds
|
|
1869
|
+
)
|
|
1870
|
+
|
|
1802
1871
|
if is_expired:
|
|
1803
1872
|
log.warning(
|
|
1804
1873
|
"%s Agent '%s' TTL has expired. De-registering. Time since last seen: %d seconds (TTL: %d seconds)",
|
|
1805
1874
|
self.log_identifier,
|
|
1806
1875
|
agent_name,
|
|
1807
1876
|
time_since_last_seen,
|
|
1808
|
-
ttl_seconds
|
|
1877
|
+
ttl_seconds,
|
|
1809
1878
|
)
|
|
1810
1879
|
agents_to_deregister.append(agent_name)
|
|
1811
|
-
|
|
1880
|
+
|
|
1812
1881
|
# De-register unresponsive agents
|
|
1813
1882
|
for agent_name in agents_to_deregister:
|
|
1814
1883
|
self._deregister_agent(agent_name)
|
|
1815
|
-
|
|
1884
|
+
|
|
1816
1885
|
log.debug(
|
|
1817
1886
|
"%s Agent health check completed. Total agents: %d, De-registered: %d",
|
|
1818
1887
|
self.log_identifier,
|
|
1819
1888
|
total_agents,
|
|
1820
|
-
len(agents_to_deregister)
|
|
1889
|
+
len(agents_to_deregister),
|
|
1821
1890
|
)
|
|
1822
|
-
|
|
1891
|
+
|
|
1823
1892
|
def _deregister_agent(self, agent_name: str):
|
|
1824
1893
|
"""
|
|
1825
1894
|
De-registers an agent from the registry and publishes a de-registration event.
|
|
@@ -2054,12 +2123,14 @@ class WebUIBackendComponent(BaseGatewayComponent):
|
|
|
2054
2123
|
return
|
|
2055
2124
|
|
|
2056
2125
|
try:
|
|
2057
|
-
from solace_agent_mesh_enterprise.auth.input_required import
|
|
2126
|
+
from solace_agent_mesh_enterprise.auth.input_required import (
|
|
2127
|
+
handle_input_required_request,
|
|
2128
|
+
)
|
|
2129
|
+
|
|
2058
2130
|
event_data = handle_input_required_request(event_data, sse_task_id, self)
|
|
2059
2131
|
except ImportError:
|
|
2060
2132
|
pass
|
|
2061
2133
|
|
|
2062
|
-
|
|
2063
2134
|
log.debug(
|
|
2064
2135
|
"%s Sending update for A2A Task ID %s to SSE Task ID %s. Final chunk: %s",
|
|
2065
2136
|
log_id_prefix,
|
|
@@ -453,17 +453,32 @@ def _run_enterprise_migrations(
|
|
|
453
453
|
raise RuntimeError(f"Enterprise database migration failed: {e}") from e
|
|
454
454
|
|
|
455
455
|
|
|
456
|
-
def _setup_database(
|
|
456
|
+
def _setup_database(
|
|
457
|
+
component: "WebUIBackendComponent",
|
|
458
|
+
database_url: str,
|
|
459
|
+
platform_database_url: str = None
|
|
460
|
+
) -> None:
|
|
457
461
|
"""
|
|
458
|
-
Initialize database
|
|
459
|
-
|
|
462
|
+
Initialize database connections and run all required migrations.
|
|
463
|
+
Sets up both runtime and platform database schemas.
|
|
464
|
+
|
|
465
|
+
Args:
|
|
466
|
+
component: WebUIBackendComponent instance
|
|
467
|
+
database_url: Runtime database URL (sessions, tasks, chat) - REQUIRED
|
|
468
|
+
platform_database_url: Platform database URL (agents, connectors, deployments).
|
|
469
|
+
If None, platform features will be unavailable.
|
|
460
470
|
"""
|
|
461
471
|
dependencies.init_database(database_url)
|
|
462
472
|
log.info("Persistence enabled - sessions will be stored in database")
|
|
463
473
|
log.info("Running database migrations...")
|
|
464
474
|
|
|
465
475
|
_run_community_migrations(database_url)
|
|
466
|
-
|
|
476
|
+
|
|
477
|
+
if platform_database_url:
|
|
478
|
+
log.info("Platform database configured - running migrations")
|
|
479
|
+
_run_enterprise_migrations(component, platform_database_url)
|
|
480
|
+
else:
|
|
481
|
+
log.info("No platform database configured - skipping platform migrations")
|
|
467
482
|
|
|
468
483
|
|
|
469
484
|
def _get_app_config(component: "WebUIBackendComponent") -> dict:
|
|
@@ -498,12 +513,20 @@ def _create_api_config(app_config: dict, database_url: str) -> dict:
|
|
|
498
513
|
}
|
|
499
514
|
|
|
500
515
|
|
|
501
|
-
def setup_dependencies(
|
|
516
|
+
def setup_dependencies(
|
|
517
|
+
component: "WebUIBackendComponent",
|
|
518
|
+
database_url: str = None,
|
|
519
|
+
platform_database_url: str = None
|
|
520
|
+
):
|
|
502
521
|
"""
|
|
503
|
-
|
|
504
|
-
backward compatibility with existing API contracts.
|
|
522
|
+
Initialize dependencies for both runtime and platform databases.
|
|
505
523
|
|
|
506
|
-
|
|
524
|
+
Args:
|
|
525
|
+
component: WebUIBackendComponent instance
|
|
526
|
+
database_url: Runtime database URL (sessions, tasks, chat).
|
|
527
|
+
If None, runs in compatibility mode with in-memory sessions.
|
|
528
|
+
platform_database_url: Platform database URL (agents, connectors, deployments).
|
|
529
|
+
If None, platform features will be unavailable (returns 501).
|
|
507
530
|
|
|
508
531
|
This function is idempotent and safe to call multiple times.
|
|
509
532
|
"""
|
|
@@ -516,7 +539,7 @@ def setup_dependencies(component: "WebUIBackendComponent", database_url: str = N
|
|
|
516
539
|
dependencies.set_component_instance(component)
|
|
517
540
|
|
|
518
541
|
if database_url:
|
|
519
|
-
_setup_database(component, database_url)
|
|
542
|
+
_setup_database(component, database_url, platform_database_url)
|
|
520
543
|
else:
|
|
521
544
|
log.warning(
|
|
522
545
|
"No database URL provided - using in-memory session storage (data not persisted across restarts)"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: solace-agent-mesh
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.3
|
|
4
4
|
Summary: Solace Agent Mesh is an open-source framework for building event-driven, multi-agent AI systems where specialized agents collaborate on complex tasks.
|
|
5
5
|
Project-URL: Homepage, https://github.com/SolaceLabs/solace-agent-mesh
|
|
6
6
|
Project-URL: Repository, https://github.com/SolaceLabs/solace-agent-mesh
|