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.
- 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 +50 -14
- solace_agent_mesh/agent/adk/setup.py +66 -38
- solace_agent_mesh/agent/protocol/event_handlers.py +416 -152
- solace_agent_mesh/agent/proxies/a2a/app.py +3 -2
- solace_agent_mesh/agent/proxies/base/app.py +3 -2
- solace_agent_mesh/agent/proxies/base/component.py +35 -4
- solace_agent_mesh/agent/sac/app.py +97 -9
- solace_agent_mesh/agent/sac/component.py +284 -145
- solace_agent_mesh/agent/sac/task_execution_context.py +79 -2
- 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/{e3d9abda.2b916f9e.js → e3d9abda.6b9493d0.js} +1 -1
- 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.d1643f0b.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.97f920d4.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 +3 -3
- 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-1761663789856.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1761663789856.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/a2a/protocol.py +78 -0
- solace_agent_mesh/common/sac/sam_component_base.py +406 -21
- solace_agent_mesh/common/utils/pydantic_utils.py +90 -3
- solace_agent_mesh/gateway/base/app.py +15 -0
- solace_agent_mesh/gateway/base/component.py +116 -46
- solace_agent_mesh/gateway/http_sse/app.py +7 -0
- solace_agent_mesh/gateway/http_sse/component.py +18 -10
- solace_agent_mesh/gateway/http_sse/dependencies.py +83 -59
- solace_agent_mesh/gateway/http_sse/main.py +5 -4
- 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/users.py +47 -1
- 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.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/METADATA +2 -2
- {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/RECORD +116 -114
- 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/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.20feee82.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.0d198646.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1761165361160.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1761165361160.json +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-BGTaW0uv.js +0 -342
- solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +0 -1
- /solace_agent_mesh/assets/docs/assets/js/{main.20feee82.js.LICENSE.txt → main.d1643f0b.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,79 +2,80 @@
|
|
|
2
2
|
Custom Solace AI Connector Component to Host Google ADK Agents via A2A Protocol.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import logging
|
|
6
|
-
from typing import Any, Dict, Optional, Union, Callable, List, Tuple, TYPE_CHECKING
|
|
7
5
|
import asyncio
|
|
8
|
-
import functools
|
|
9
|
-
import threading
|
|
10
6
|
import concurrent.futures
|
|
11
7
|
import fnmatch
|
|
12
|
-
import
|
|
8
|
+
import functools
|
|
9
|
+
import inspect
|
|
13
10
|
import json
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
from
|
|
11
|
+
import logging
|
|
12
|
+
import threading
|
|
13
|
+
import time
|
|
14
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
|
|
18
15
|
|
|
19
|
-
from solace_ai_connector.common.utils import import_module
|
|
20
|
-
import inspect
|
|
21
|
-
from pydantic import BaseModel, ValidationError
|
|
22
|
-
from google.adk.agents.invocation_context import (
|
|
23
|
-
LlmCallsLimitExceededError,
|
|
24
|
-
)
|
|
25
|
-
from google.adk.agents import RunConfig
|
|
26
|
-
from google.adk.agents.run_config import StreamingMode
|
|
27
|
-
from google.adk.sessions import BaseSessionService
|
|
28
|
-
from google.adk.artifacts import BaseArtifactService
|
|
29
|
-
from google.adk.memory import BaseMemoryService
|
|
30
|
-
from google.adk.agents import LlmAgent
|
|
31
|
-
from google.adk.runners import Runner
|
|
32
|
-
from google.adk.models import LlmResponse
|
|
33
|
-
from google.adk.agents.readonly_context import ReadonlyContext
|
|
34
|
-
from google.adk.events import Event as ADKEvent
|
|
35
|
-
from google.adk.agents.callback_context import CallbackContext
|
|
36
|
-
from google.adk.models.llm_request import LlmRequest
|
|
37
|
-
from google.genai import types as adk_types
|
|
38
|
-
from google.adk.tools.mcp_tool import MCPToolset
|
|
39
16
|
from a2a.types import (
|
|
40
17
|
AgentCard,
|
|
41
|
-
Artifact as A2AArtifact,
|
|
42
|
-
Message as A2AMessage,
|
|
43
18
|
MessageSendParams,
|
|
44
19
|
SendMessageRequest,
|
|
45
20
|
TaskState,
|
|
46
21
|
TaskStatus,
|
|
47
22
|
TaskStatusUpdateEvent,
|
|
48
23
|
)
|
|
49
|
-
from
|
|
50
|
-
from
|
|
51
|
-
from
|
|
52
|
-
from
|
|
24
|
+
from a2a.types import Artifact as A2AArtifact
|
|
25
|
+
from a2a.types import Message as A2AMessage
|
|
26
|
+
from google.adk.agents import LlmAgent, RunConfig
|
|
27
|
+
from google.adk.agents.callback_context import CallbackContext
|
|
28
|
+
from google.adk.agents.invocation_context import LlmCallsLimitExceededError
|
|
29
|
+
from google.adk.agents.readonly_context import ReadonlyContext
|
|
30
|
+
from google.adk.agents.run_config import StreamingMode
|
|
31
|
+
from google.adk.artifacts import BaseArtifactService
|
|
32
|
+
from google.adk.auth.credential_service.base_credential_service import (
|
|
33
|
+
BaseCredentialService,
|
|
34
|
+
)
|
|
35
|
+
from google.adk.events import Event as ADKEvent
|
|
36
|
+
from google.adk.memory import BaseMemoryService
|
|
37
|
+
from google.adk.models import LlmResponse
|
|
38
|
+
from google.adk.models.llm_request import LlmRequest
|
|
39
|
+
from google.adk.runners import Runner
|
|
40
|
+
from google.adk.sessions import BaseSessionService
|
|
41
|
+
from google.adk.tools.mcp_tool import MCPToolset
|
|
42
|
+
from google.genai import types as adk_types
|
|
43
|
+
from pydantic import BaseModel, ValidationError
|
|
44
|
+
from solace_ai_connector.common.event import Event, EventType
|
|
45
|
+
from solace_ai_connector.common.message import Message as SolaceMessage
|
|
46
|
+
from solace_ai_connector.common.utils import import_module
|
|
47
|
+
|
|
48
|
+
from ...agent.adk.runner import TaskCancelledError, run_adk_async_task_thread_wrapper
|
|
53
49
|
from ...agent.adk.services import (
|
|
54
|
-
initialize_session_service,
|
|
55
50
|
initialize_artifact_service,
|
|
51
|
+
initialize_credential_service,
|
|
56
52
|
initialize_memory_service,
|
|
53
|
+
initialize_session_service,
|
|
57
54
|
)
|
|
58
55
|
from ...agent.adk.setup import (
|
|
59
|
-
load_adk_tools,
|
|
60
56
|
initialize_adk_agent,
|
|
61
57
|
initialize_adk_runner,
|
|
58
|
+
load_adk_tools,
|
|
62
59
|
)
|
|
63
|
-
from ...agent.protocol.event_handlers import
|
|
64
|
-
process_event,
|
|
65
|
-
publish_agent_card,
|
|
66
|
-
)
|
|
67
|
-
from ...agent.adk.runner import run_adk_async_task_thread_wrapper, TaskCancelledError
|
|
60
|
+
from ...agent.protocol.event_handlers import process_event, publish_agent_card
|
|
68
61
|
from ...agent.tools.peer_agent_tool import (
|
|
69
62
|
CORRELATION_DATA_PREFIX,
|
|
70
|
-
PeerAgentTool,
|
|
71
63
|
PEER_TOOL_PREFIX,
|
|
64
|
+
PeerAgentTool,
|
|
72
65
|
)
|
|
73
|
-
from ...common.middleware.registry import MiddlewareRegistry
|
|
74
|
-
from ...common.constants import DEFAULT_COMMUNICATION_TIMEOUT, HEALTH_CHECK_TTL_SECONDS, HEALTH_CHECK_INTERVAL_SECONDS
|
|
75
66
|
from ...agent.tools.registry import tool_registry
|
|
76
|
-
from ...
|
|
67
|
+
from ...agent.utils.config_parser import resolve_instruction_provider
|
|
68
|
+
from ...common import a2a
|
|
69
|
+
from ...common.a2a.translation import format_and_route_adk_event
|
|
77
70
|
from ...common.agent_registry import AgentRegistry
|
|
71
|
+
from ...common.constants import (
|
|
72
|
+
DEFAULT_COMMUNICATION_TIMEOUT,
|
|
73
|
+
HEALTH_CHECK_INTERVAL_SECONDS,
|
|
74
|
+
HEALTH_CHECK_TTL_SECONDS,
|
|
75
|
+
)
|
|
76
|
+
from ...common.data_parts import AgentProgressUpdateData
|
|
77
|
+
from ...common.middleware.registry import MiddlewareRegistry
|
|
78
|
+
from ...common.sac.sam_component_base import SamComponentBase
|
|
78
79
|
|
|
79
80
|
log = logging.getLogger(__name__)
|
|
80
81
|
|
|
@@ -103,7 +104,6 @@ info = {
|
|
|
103
104
|
}
|
|
104
105
|
InstructionProvider = Callable[[ReadonlyContext], str]
|
|
105
106
|
|
|
106
|
-
|
|
107
107
|
class SamAgentComponent(SamComponentBase):
|
|
108
108
|
"""
|
|
109
109
|
A Solace AI Connector component that hosts a Google ADK agent,
|
|
@@ -128,7 +128,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
128
128
|
|
|
129
129
|
super().__init__(info, **kwargs)
|
|
130
130
|
self.agent_name = self.get_config("agent_name")
|
|
131
|
-
log.info("%s Initializing A2A ADK Host Component...", self.log_identifier)
|
|
131
|
+
log.info("%s Initializing agent: %s (A2A ADK Host Component)...", self.log_identifier, self.agent_name)
|
|
132
132
|
|
|
133
133
|
# Initialize the agent registry for health tracking
|
|
134
134
|
self.agent_registry = AgentRegistry()
|
|
@@ -226,7 +226,6 @@ class SamAgentComponent(SamComponentBase):
|
|
|
226
226
|
"max_message_size_bytes", 10_000_000
|
|
227
227
|
)
|
|
228
228
|
|
|
229
|
-
log.info("%s Configuration retrieved successfully.", self.log_identifier)
|
|
230
229
|
except Exception as e:
|
|
231
230
|
log.error(
|
|
232
231
|
"%s Failed to retrieve configuration via get_config: %s",
|
|
@@ -237,6 +236,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
237
236
|
self.session_service: BaseSessionService = None
|
|
238
237
|
self.artifact_service: BaseArtifactService = None
|
|
239
238
|
self.memory_service: BaseMemoryService = None
|
|
239
|
+
self.credential_service: Optional[BaseCredentialService] = None
|
|
240
240
|
self.adk_agent: LlmAgent = None
|
|
241
241
|
self.runner: Runner = None
|
|
242
242
|
self.agent_card_tool_manifest: List[Dict[str, Any]] = []
|
|
@@ -265,9 +265,10 @@ class SamAgentComponent(SamComponentBase):
|
|
|
265
265
|
self.session_service = initialize_session_service(self)
|
|
266
266
|
self.artifact_service = initialize_artifact_service(self)
|
|
267
267
|
self.memory_service = initialize_memory_service(self)
|
|
268
|
+
self.credential_service = initialize_credential_service(self)
|
|
268
269
|
|
|
269
270
|
log.info(
|
|
270
|
-
"%s Synchronous ADK services
|
|
271
|
+
"%s Initialized Synchronous ADK services.", self.log_identifier
|
|
271
272
|
)
|
|
272
273
|
except Exception as service_err:
|
|
273
274
|
log.exception(
|
|
@@ -279,8 +280,25 @@ class SamAgentComponent(SamComponentBase):
|
|
|
279
280
|
f"Failed to initialize synchronous ADK services: {service_err}"
|
|
280
281
|
) from service_err
|
|
281
282
|
|
|
282
|
-
|
|
283
|
-
|
|
283
|
+
# initialize enterprise features if available
|
|
284
|
+
try:
|
|
285
|
+
from solace_agent_mesh_enterprise.init_enterprise_component import (
|
|
286
|
+
init_enterprise_component_features,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
init_enterprise_component_features(self)
|
|
290
|
+
except ImportError:
|
|
291
|
+
# Community edition
|
|
292
|
+
# Contact Solace support for enterprise features
|
|
293
|
+
pass
|
|
294
|
+
|
|
295
|
+
from .app import (
|
|
296
|
+
AgentInitCleanupConfig,
|
|
297
|
+
) # delayed import to avoid circular dependency
|
|
298
|
+
|
|
299
|
+
if init_func_details and isinstance(
|
|
300
|
+
init_func_details, AgentInitCleanupConfig
|
|
301
|
+
):
|
|
284
302
|
module_name = init_func_details.get("module")
|
|
285
303
|
func_name = init_func_details.get("name")
|
|
286
304
|
base_path = init_func_details.get("base_path")
|
|
@@ -407,10 +425,12 @@ class SamAgentComponent(SamComponentBase):
|
|
|
407
425
|
self.log_identifier,
|
|
408
426
|
publish_interval_sec,
|
|
409
427
|
)
|
|
428
|
+
# Register timer with callback
|
|
410
429
|
self.add_timer(
|
|
411
430
|
delay_ms=1000,
|
|
412
431
|
timer_id=self._card_publish_timer_id,
|
|
413
432
|
interval_ms=publish_interval_sec * 1000,
|
|
433
|
+
callback=lambda timer_data: publish_agent_card(self),
|
|
414
434
|
)
|
|
415
435
|
else:
|
|
416
436
|
log.warning(
|
|
@@ -430,6 +450,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
430
450
|
delay_ms=health_check_interval_seconds * 1000,
|
|
431
451
|
timer_id=self.HEALTH_CHECK_TIMER_ID,
|
|
432
452
|
interval_ms=health_check_interval_seconds * 1000,
|
|
453
|
+
callback=lambda timer_data: self._check_agent_health(),
|
|
433
454
|
)
|
|
434
455
|
else:
|
|
435
456
|
log.warning(
|
|
@@ -438,7 +459,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
438
459
|
)
|
|
439
460
|
|
|
440
461
|
log.info(
|
|
441
|
-
"%s
|
|
462
|
+
"%s Initialized agent: %s",
|
|
442
463
|
self.log_identifier,
|
|
443
464
|
self.agent_name,
|
|
444
465
|
)
|
|
@@ -446,79 +467,35 @@ class SamAgentComponent(SamComponentBase):
|
|
|
446
467
|
log.exception("%s Initialization failed: %s", self.log_identifier, e)
|
|
447
468
|
raise
|
|
448
469
|
|
|
470
|
+
def _get_component_id(self) -> str:
|
|
471
|
+
"""Returns the agent name as the component identifier."""
|
|
472
|
+
return self.agent_name
|
|
473
|
+
|
|
474
|
+
def _get_component_type(self) -> str:
|
|
475
|
+
"""Returns 'agent' as the component type."""
|
|
476
|
+
return "agent"
|
|
477
|
+
|
|
449
478
|
def invoke(self, message: SolaceMessage, data: dict) -> dict:
|
|
450
|
-
"""Placeholder invoke method. Primary logic resides in
|
|
479
|
+
"""Placeholder invoke method. Primary logic resides in _handle_message."""
|
|
451
480
|
log.warning(
|
|
452
|
-
"%s 'invoke' method called, but primary logic resides in '
|
|
481
|
+
"%s 'invoke' method called, but primary logic resides in '_handle_message'. This should not happen in normal operation.",
|
|
453
482
|
self.log_identifier,
|
|
454
483
|
)
|
|
455
484
|
return None
|
|
456
485
|
|
|
457
|
-
def
|
|
458
|
-
"""
|
|
459
|
-
|
|
460
|
-
loop = self.get_async_loop()
|
|
461
|
-
is_loop_running = loop.is_running() if loop else False
|
|
462
|
-
if loop and is_loop_running:
|
|
463
|
-
coro = process_event(self, event)
|
|
464
|
-
future = asyncio.run_coroutine_threadsafe(coro, loop)
|
|
465
|
-
future.add_done_callback(
|
|
466
|
-
functools.partial(
|
|
467
|
-
self._handle_scheduled_task_completion,
|
|
468
|
-
event_type_for_log=event.event_type,
|
|
469
|
-
)
|
|
470
|
-
)
|
|
471
|
-
else:
|
|
472
|
-
log.error(
|
|
473
|
-
"%s Async loop not available or not running (loop is %s, is_running: %s). Cannot process event: %s",
|
|
474
|
-
self.log_identifier,
|
|
475
|
-
"present" if loop else "None",
|
|
476
|
-
is_loop_running,
|
|
477
|
-
event.event_type,
|
|
478
|
-
)
|
|
479
|
-
if event.event_type == EventType.MESSAGE:
|
|
480
|
-
try:
|
|
481
|
-
event.data.call_negative_acknowledgements()
|
|
482
|
-
log.warning(
|
|
483
|
-
"%s NACKed message due to unavailable async loop for event processing.",
|
|
484
|
-
self.log_identifier,
|
|
485
|
-
)
|
|
486
|
-
except Exception as nack_e:
|
|
487
|
-
log.error(
|
|
488
|
-
"%s Failed to NACK message after async loop issue: %s",
|
|
489
|
-
self.log_identifier,
|
|
490
|
-
nack_e,
|
|
491
|
-
)
|
|
492
|
-
except Exception as e:
|
|
493
|
-
log.error(
|
|
494
|
-
"%s Error processing event: %s. Exception: %s",
|
|
495
|
-
self.log_identifier,
|
|
496
|
-
event.event_type,
|
|
497
|
-
e,
|
|
498
|
-
)
|
|
499
|
-
if event.event_type == EventType.MESSAGE:
|
|
500
|
-
try:
|
|
501
|
-
event.data.call_negative_acknowledgements()
|
|
502
|
-
log.warning(
|
|
503
|
-
"%s NACKed message due to error in event processing.",
|
|
504
|
-
self.log_identifier,
|
|
505
|
-
)
|
|
506
|
-
except Exception as nack_e:
|
|
507
|
-
log.error(
|
|
508
|
-
"%s Failed to NACK message after error in event processing: %s",
|
|
509
|
-
self.log_identifier,
|
|
510
|
-
nack_e,
|
|
511
|
-
)
|
|
486
|
+
async def _handle_message_async(self, message: SolaceMessage, topic: str) -> None:
|
|
487
|
+
"""
|
|
488
|
+
Async handler for incoming messages.
|
|
512
489
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
490
|
+
Routes the message to the async event handler.
|
|
491
|
+
|
|
492
|
+
Args:
|
|
493
|
+
message: The Solace message
|
|
494
|
+
topic: The topic the message was received on
|
|
495
|
+
"""
|
|
496
|
+
# Create event and process asynchronously
|
|
497
|
+
event = Event(EventType.MESSAGE, message)
|
|
498
|
+
await process_event(self, event)
|
|
522
499
|
|
|
523
500
|
async def handle_cache_expiry_event(self, cache_data: Dict[str, Any]):
|
|
524
501
|
"""
|
|
@@ -559,6 +536,83 @@ class SamAgentComponent(SamComponentBase):
|
|
|
559
536
|
sub_task_id,
|
|
560
537
|
)
|
|
561
538
|
|
|
539
|
+
async def get_main_task_context(
|
|
540
|
+
self, logical_task_id: str
|
|
541
|
+
) -> Optional["TaskExecutionContext"]:
|
|
542
|
+
"""
|
|
543
|
+
Retrieves the main task context for a given logical task ID.
|
|
544
|
+
|
|
545
|
+
This method is used when the current agent is the target agent for the task.
|
|
546
|
+
It returns the TaskExecutionContext which contains the full task state including
|
|
547
|
+
a2a_context, active_peer_sub_tasks, and other task execution details.
|
|
548
|
+
|
|
549
|
+
Args:
|
|
550
|
+
logical_task_id: The unique logical ID of the task
|
|
551
|
+
|
|
552
|
+
Returns:
|
|
553
|
+
The TaskExecutionContext if the task is active, None otherwise
|
|
554
|
+
|
|
555
|
+
Raises:
|
|
556
|
+
ValueError: If logical_task_id is None or empty
|
|
557
|
+
"""
|
|
558
|
+
if not logical_task_id:
|
|
559
|
+
raise ValueError("logical_task_id cannot be None or empty")
|
|
560
|
+
|
|
561
|
+
with self.active_tasks_lock:
|
|
562
|
+
active_task_context = self.active_tasks.get(logical_task_id)
|
|
563
|
+
if active_task_context is None:
|
|
564
|
+
log.warning(
|
|
565
|
+
f"No active task context found for logical_task_id: {logical_task_id}"
|
|
566
|
+
)
|
|
567
|
+
return None
|
|
568
|
+
|
|
569
|
+
return active_task_context
|
|
570
|
+
|
|
571
|
+
async def get_all_sub_task_correlation_data_from_logical_task_id(
|
|
572
|
+
self, logical_task_id: str
|
|
573
|
+
) -> list[dict[str, Any]]:
|
|
574
|
+
"""
|
|
575
|
+
Retrieves correlation data for all active peer sub-tasks of a given logical task.
|
|
576
|
+
|
|
577
|
+
This method is used when forwarding requests to other agents in an A2A workflow.
|
|
578
|
+
It returns a list of correlation data dictionaries, each containing information
|
|
579
|
+
about a peer sub-task including peer_task_id, peer_agent_name, and original_task_context.
|
|
580
|
+
|
|
581
|
+
Args:
|
|
582
|
+
logical_task_id: The unique logical ID of the parent task
|
|
583
|
+
|
|
584
|
+
Returns:
|
|
585
|
+
List of correlation data dictionaries for active peer sub-tasks.
|
|
586
|
+
Returns empty list if no active peer sub-tasks exist.
|
|
587
|
+
|
|
588
|
+
Raises:
|
|
589
|
+
ValueError: If logical_task_id is None or empty
|
|
590
|
+
"""
|
|
591
|
+
if not logical_task_id:
|
|
592
|
+
raise ValueError("logical_task_id cannot be None or empty")
|
|
593
|
+
|
|
594
|
+
with self.active_tasks_lock:
|
|
595
|
+
active_task_context = self.active_tasks.get(logical_task_id)
|
|
596
|
+
if active_task_context is None:
|
|
597
|
+
log.warning(
|
|
598
|
+
f"No active task context found for logical_task_id: {logical_task_id}"
|
|
599
|
+
)
|
|
600
|
+
return []
|
|
601
|
+
|
|
602
|
+
active_peer_sub_tasks = active_task_context.active_peer_sub_tasks
|
|
603
|
+
if not active_peer_sub_tasks:
|
|
604
|
+
log.debug(
|
|
605
|
+
f"No active peer sub-tasks found for logical_task_id: {logical_task_id}"
|
|
606
|
+
)
|
|
607
|
+
return []
|
|
608
|
+
|
|
609
|
+
results = []
|
|
610
|
+
for sub_task_id, correlation_data in active_peer_sub_tasks.items():
|
|
611
|
+
if sub_task_id is not None and correlation_data is not None:
|
|
612
|
+
results.append(correlation_data)
|
|
613
|
+
|
|
614
|
+
return results
|
|
615
|
+
|
|
562
616
|
async def _get_correlation_data_for_sub_task(
|
|
563
617
|
self, sub_task_id: str
|
|
564
618
|
) -> Optional[Dict[str, Any]]:
|
|
@@ -1168,7 +1222,11 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1168
1222
|
"""
|
|
1169
1223
|
if hasattr(tool, "origin") and tool.origin is not None:
|
|
1170
1224
|
return tool.origin
|
|
1171
|
-
elif
|
|
1225
|
+
elif (
|
|
1226
|
+
hasattr(tool, "func")
|
|
1227
|
+
and hasattr(tool.func, "origin")
|
|
1228
|
+
and tool.func.origin is not None
|
|
1229
|
+
):
|
|
1172
1230
|
return tool.func.origin
|
|
1173
1231
|
else:
|
|
1174
1232
|
return getattr(tool, "origin", "unknown")
|
|
@@ -1546,7 +1604,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1546
1604
|
payload_to_publish, target_topic, a2a_context, user_properties
|
|
1547
1605
|
)
|
|
1548
1606
|
|
|
1549
|
-
log.
|
|
1607
|
+
log.debug(
|
|
1550
1608
|
"%s Published %s status update to %s.",
|
|
1551
1609
|
log_identifier,
|
|
1552
1610
|
status_type,
|
|
@@ -1659,6 +1717,19 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1659
1717
|
is_run_based_session = a2a_context.get("is_run_based_session", False)
|
|
1660
1718
|
is_final_turn_event = not adk_event.partial
|
|
1661
1719
|
|
|
1720
|
+
try:
|
|
1721
|
+
from solace_agent_mesh_enterprise.auth.tool_auth import handle_tool_auth_event
|
|
1722
|
+
auth_status_update = await handle_tool_auth_event(adk_event, self, a2a_context)
|
|
1723
|
+
if auth_status_update:
|
|
1724
|
+
await self._publish_status_update_with_buffer_flush(
|
|
1725
|
+
auth_status_update,
|
|
1726
|
+
a2a_context,
|
|
1727
|
+
skip_buffer_flush=False,
|
|
1728
|
+
)
|
|
1729
|
+
return
|
|
1730
|
+
except ImportError:
|
|
1731
|
+
pass
|
|
1732
|
+
|
|
1662
1733
|
if not is_final_turn_event:
|
|
1663
1734
|
if adk_event.content and adk_event.content.parts:
|
|
1664
1735
|
for part in adk_event.content.parts:
|
|
@@ -1687,7 +1758,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1687
1758
|
)
|
|
1688
1759
|
|
|
1689
1760
|
if buffer_has_content and (batching_disabled or threshold_met):
|
|
1690
|
-
log.
|
|
1761
|
+
log.debug(
|
|
1691
1762
|
"%s Partial event triggered buffer flush due to size/batching config.",
|
|
1692
1763
|
log_id_main,
|
|
1693
1764
|
)
|
|
@@ -1710,7 +1781,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1710
1781
|
else:
|
|
1711
1782
|
buffer_content = task_context.get_streaming_buffer_content()
|
|
1712
1783
|
if buffer_content:
|
|
1713
|
-
log.
|
|
1784
|
+
log.debug(
|
|
1714
1785
|
"%s Final event triggered flush of remaining buffer content.",
|
|
1715
1786
|
log_id_main,
|
|
1716
1787
|
)
|
|
@@ -1744,7 +1815,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1744
1815
|
|
|
1745
1816
|
if a2a_payload and target_topic:
|
|
1746
1817
|
self._publish_a2a_event(a2a_payload, target_topic, a2a_context)
|
|
1747
|
-
log.
|
|
1818
|
+
log.debug(
|
|
1748
1819
|
"%s Published final turn event (e.g., tool call) to %s.",
|
|
1749
1820
|
log_id_main,
|
|
1750
1821
|
target_topic,
|
|
@@ -2030,9 +2101,14 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2030
2101
|
For STREAMING tasks, it uses the content of the last ADK event.
|
|
2031
2102
|
"""
|
|
2032
2103
|
logical_task_id = a2a_context.get("logical_task_id")
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2104
|
+
|
|
2105
|
+
# Retrieve the original Solace message from TaskExecutionContext
|
|
2106
|
+
original_message: Optional[SolaceMessage] = None
|
|
2107
|
+
with self.active_tasks_lock:
|
|
2108
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2109
|
+
if task_context:
|
|
2110
|
+
original_message = task_context.get_original_solace_message()
|
|
2111
|
+
|
|
2036
2112
|
log.info(
|
|
2037
2113
|
"%s Finalizing task %s successfully.", self.log_identifier, logical_task_id
|
|
2038
2114
|
)
|
|
@@ -2106,7 +2182,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2106
2182
|
self.log_identifier,
|
|
2107
2183
|
len(task_context.produced_artifacts),
|
|
2108
2184
|
)
|
|
2109
|
-
|
|
2185
|
+
|
|
2110
2186
|
# Add token usage summary
|
|
2111
2187
|
if task_context:
|
|
2112
2188
|
token_summary = task_context.get_token_usage_summary()
|
|
@@ -2226,9 +2302,14 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2226
2302
|
Called by the background ADK thread wrapper when a task is cancelled.
|
|
2227
2303
|
"""
|
|
2228
2304
|
logical_task_id = a2a_context.get("logical_task_id")
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2305
|
+
|
|
2306
|
+
# Retrieve the original Solace message from TaskExecutionContext
|
|
2307
|
+
original_message: Optional[SolaceMessage] = None
|
|
2308
|
+
with self.active_tasks_lock:
|
|
2309
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2310
|
+
if task_context:
|
|
2311
|
+
original_message = task_context.get_original_solace_message()
|
|
2312
|
+
|
|
2232
2313
|
log.info(
|
|
2233
2314
|
"%s Finalizing task %s as CANCELED.", self.log_identifier, logical_task_id
|
|
2234
2315
|
)
|
|
@@ -2430,9 +2511,14 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2430
2511
|
Sends a COMPLETED status with an informative message.
|
|
2431
2512
|
"""
|
|
2432
2513
|
logical_task_id = a2a_context.get("logical_task_id")
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2514
|
+
|
|
2515
|
+
# Retrieve the original Solace message from TaskExecutionContext
|
|
2516
|
+
original_message: Optional[SolaceMessage] = None
|
|
2517
|
+
with self.active_tasks_lock:
|
|
2518
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2519
|
+
if task_context:
|
|
2520
|
+
original_message = task_context.get_original_solace_message()
|
|
2521
|
+
|
|
2436
2522
|
log.info(
|
|
2437
2523
|
"%s Finalizing task %s as COMPLETED (LLM call limit reached).",
|
|
2438
2524
|
self.log_identifier,
|
|
@@ -2509,9 +2595,14 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2509
2595
|
Called by the background ADK thread wrapper.
|
|
2510
2596
|
"""
|
|
2511
2597
|
logical_task_id = a2a_context.get("logical_task_id")
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2598
|
+
|
|
2599
|
+
# Retrieve the original Solace message from TaskExecutionContext
|
|
2600
|
+
original_message: Optional[SolaceMessage] = None
|
|
2601
|
+
with self.active_tasks_lock:
|
|
2602
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2603
|
+
if task_context:
|
|
2604
|
+
original_message = task_context.get_original_solace_message()
|
|
2605
|
+
|
|
2515
2606
|
log.error(
|
|
2516
2607
|
"%s Finalizing task %s with error: %s",
|
|
2517
2608
|
self.log_identifier,
|
|
@@ -2654,9 +2745,13 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2654
2745
|
log_id,
|
|
2655
2746
|
e,
|
|
2656
2747
|
)
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2748
|
+
# Retrieve the original Solace message from TaskExecutionContext for fallback NACK
|
|
2749
|
+
original_message: Optional[SolaceMessage] = None
|
|
2750
|
+
with self.active_tasks_lock:
|
|
2751
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2752
|
+
if task_context:
|
|
2753
|
+
original_message = task_context.get_original_solace_message()
|
|
2754
|
+
|
|
2660
2755
|
if original_message:
|
|
2661
2756
|
try:
|
|
2662
2757
|
original_message.call_negative_acknowledgements()
|
|
@@ -2857,10 +2952,40 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2857
2952
|
"replyTo": reply_to_topic,
|
|
2858
2953
|
"a2aStatusTopic": status_topic,
|
|
2859
2954
|
"userId": user_id,
|
|
2955
|
+
"delegating_agent_name": delegating_agent_name,
|
|
2860
2956
|
}
|
|
2861
2957
|
if isinstance(user_config, dict):
|
|
2862
2958
|
user_properties["a2aUserConfig"] = user_config
|
|
2863
2959
|
|
|
2960
|
+
# Retrieve and propagate authentication token from parent task context
|
|
2961
|
+
parent_task_id = a2a_message.metadata.get("parentTaskId")
|
|
2962
|
+
if parent_task_id:
|
|
2963
|
+
with self.active_tasks_lock:
|
|
2964
|
+
parent_task_context = self.active_tasks.get(parent_task_id)
|
|
2965
|
+
|
|
2966
|
+
if parent_task_context:
|
|
2967
|
+
auth_token = parent_task_context.get_security_data("auth_token")
|
|
2968
|
+
if auth_token:
|
|
2969
|
+
user_properties["authToken"] = auth_token
|
|
2970
|
+
log.debug(
|
|
2971
|
+
"%s Propagating authentication token to peer agent %s for sub-task %s",
|
|
2972
|
+
log_identifier_helper,
|
|
2973
|
+
target_agent_name,
|
|
2974
|
+
sub_task_id,
|
|
2975
|
+
)
|
|
2976
|
+
else:
|
|
2977
|
+
log.debug(
|
|
2978
|
+
"%s No authentication token found in parent task context for sub-task %s",
|
|
2979
|
+
log_identifier_helper,
|
|
2980
|
+
sub_task_id,
|
|
2981
|
+
)
|
|
2982
|
+
else:
|
|
2983
|
+
log.warning(
|
|
2984
|
+
"%s Parent task context not found for task %s, cannot propagate authentication token",
|
|
2985
|
+
log_identifier_helper,
|
|
2986
|
+
parent_task_id,
|
|
2987
|
+
)
|
|
2988
|
+
|
|
2864
2989
|
self.publish_a2a_message(
|
|
2865
2990
|
payload=a2a_request.model_dump(by_alias=True, exclude_none=True),
|
|
2866
2991
|
topic=peer_request_topic,
|
|
@@ -3023,8 +3148,11 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3023
3148
|
|
|
3024
3149
|
cleanup_func_details = self.get_config("agent_cleanup_function")
|
|
3025
3150
|
|
|
3026
|
-
from .app import AgentInitCleanupConfig
|
|
3027
|
-
|
|
3151
|
+
from .app import AgentInitCleanupConfig # Avoid circular import
|
|
3152
|
+
|
|
3153
|
+
if cleanup_func_details and isinstance(
|
|
3154
|
+
cleanup_func_details, AgentInitCleanupConfig
|
|
3155
|
+
):
|
|
3028
3156
|
module_name = cleanup_func_details.get("module")
|
|
3029
3157
|
func_name = cleanup_func_details.get("name")
|
|
3030
3158
|
base_path = cleanup_func_details.get("base_path")
|
|
@@ -3356,11 +3484,11 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3356
3484
|
resolver_config = context_for_embeds["config"]
|
|
3357
3485
|
|
|
3358
3486
|
try:
|
|
3487
|
+
from ...common.utils.embeds.constants import EARLY_EMBED_TYPES
|
|
3359
3488
|
from ...common.utils.embeds.resolver import (
|
|
3360
|
-
resolve_embeds_in_string,
|
|
3361
3489
|
evaluate_embed,
|
|
3490
|
+
resolve_embeds_in_string,
|
|
3362
3491
|
)
|
|
3363
|
-
from ...common.utils.embeds.constants import EARLY_EMBED_TYPES
|
|
3364
3492
|
|
|
3365
3493
|
resolved_text, processed_until_index, signals_found = (
|
|
3366
3494
|
await resolve_embeds_in_string(
|
|
@@ -3392,6 +3520,10 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3392
3520
|
Main async logic for the agent component.
|
|
3393
3521
|
This is called by the base class's `_run_async_operations`.
|
|
3394
3522
|
"""
|
|
3523
|
+
# Call base class to initialize Trust Manager
|
|
3524
|
+
await super()._async_setup_and_run()
|
|
3525
|
+
|
|
3526
|
+
# Perform agent-specific async initialization
|
|
3395
3527
|
await self._perform_async_init()
|
|
3396
3528
|
|
|
3397
3529
|
def _pre_async_cleanup(self) -> None:
|
|
@@ -3399,4 +3531,11 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3399
3531
|
Pre-cleanup actions for the agent component.
|
|
3400
3532
|
Called by the base class before stopping the async loop.
|
|
3401
3533
|
"""
|
|
3402
|
-
|
|
3534
|
+
# Cleanup Trust Manager if present (ENTERPRISE FEATURE)
|
|
3535
|
+
if self.trust_manager:
|
|
3536
|
+
try:
|
|
3537
|
+
self.trust_manager.cleanup(self.cancel_timer)
|
|
3538
|
+
except Exception as e:
|
|
3539
|
+
log.error(
|
|
3540
|
+
"%s Error during Trust Manager cleanup: %s", self.log_identifier, e
|
|
3541
|
+
)
|