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,52 +2,106 @@
|
|
|
2
2
|
Contains event handling logic for the A2A_ADK_HostComponent.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import logging
|
|
6
|
-
import json
|
|
7
5
|
import asyncio
|
|
8
|
-
from typing import TYPE_CHECKING, Dict, Any
|
|
9
6
|
import fnmatch
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
from solace_ai_connector.common.event import Event, EventType
|
|
7
|
+
import json
|
|
8
|
+
import logging
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Dict
|
|
10
|
+
|
|
15
11
|
from a2a.types import (
|
|
16
12
|
A2ARequest,
|
|
17
|
-
AgentCard,
|
|
18
13
|
AgentCapabilities,
|
|
14
|
+
AgentCard,
|
|
19
15
|
AgentExtension,
|
|
20
16
|
DataPart,
|
|
21
17
|
JSONRPCResponse,
|
|
22
18
|
Task,
|
|
23
19
|
TaskArtifactUpdateEvent,
|
|
20
|
+
TaskState,
|
|
24
21
|
TaskStatusUpdateEvent,
|
|
25
22
|
TextPart,
|
|
26
23
|
)
|
|
24
|
+
from google.adk.agents import RunConfig
|
|
25
|
+
from google.adk.agents.run_config import StreamingMode
|
|
26
|
+
from solace_ai_connector.common.event import Event, EventType
|
|
27
|
+
from solace_ai_connector.common.message import Message as SolaceMessage
|
|
28
|
+
|
|
29
|
+
from ...agent.adk.callbacks import _publish_data_part_status_update
|
|
30
|
+
from ...agent.adk.runner import run_adk_async_task_thread_wrapper
|
|
31
|
+
from ...agent.utils.artifact_helpers import generate_artifact_metadata_summary
|
|
27
32
|
from ...common import a2a
|
|
28
33
|
from ...common.a2a import (
|
|
29
34
|
get_agent_request_topic,
|
|
30
|
-
get_discovery_topic,
|
|
31
|
-
translate_a2a_to_adk_content,
|
|
32
|
-
get_client_response_topic,
|
|
33
35
|
get_agent_response_subscription_topic,
|
|
34
36
|
get_agent_status_subscription_topic,
|
|
37
|
+
get_client_response_topic,
|
|
38
|
+
get_discovery_topic,
|
|
35
39
|
get_sam_events_subscription_topic,
|
|
36
40
|
get_text_from_message,
|
|
37
41
|
topic_matches_subscription,
|
|
42
|
+
translate_a2a_to_adk_content,
|
|
38
43
|
)
|
|
39
|
-
from ...
|
|
40
|
-
|
|
41
|
-
)
|
|
42
|
-
from ...agent.adk.runner import run_adk_async_task_thread_wrapper
|
|
44
|
+
from ...common.a2a.types import ToolsExtensionParams
|
|
45
|
+
from ...common.data_parts import ToolResultData
|
|
43
46
|
from ..sac.task_execution_context import TaskExecutionContext
|
|
44
|
-
from google.adk.agents import RunConfig
|
|
45
47
|
|
|
46
48
|
if TYPE_CHECKING:
|
|
47
49
|
from ..sac.component import SamAgentComponent
|
|
48
|
-
from google.adk.agents.run_config import StreamingMode
|
|
49
50
|
|
|
50
51
|
log = logging.getLogger(__name__)
|
|
52
|
+
trace_logger = logging.getLogger("sam_trace")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _forward_jsonrpc_response(
|
|
56
|
+
component: "SamAgentComponent",
|
|
57
|
+
original_jsonrpc_request_id: str,
|
|
58
|
+
result_data: Any,
|
|
59
|
+
target_topic: str,
|
|
60
|
+
main_logical_task_id: str,
|
|
61
|
+
peer_agent_name: str,
|
|
62
|
+
message: SolaceMessage,
|
|
63
|
+
) -> None:
|
|
64
|
+
"""
|
|
65
|
+
Utility method to forward a JSONRPCResponse with the given result data.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
component: The SamAgentComponent instance
|
|
69
|
+
original_jsonrpc_request_id: The original JSONRPC request ID
|
|
70
|
+
result_data: The data to include in the response result
|
|
71
|
+
target_topic: The topic to publish to
|
|
72
|
+
main_logical_task_id: The main logical task ID for logging
|
|
73
|
+
peer_agent_name: The peer agent name for logging
|
|
74
|
+
message: The original message to acknowledge
|
|
75
|
+
"""
|
|
76
|
+
forwarded_rpc_response = JSONRPCResponse(
|
|
77
|
+
id=original_jsonrpc_request_id,
|
|
78
|
+
result=result_data,
|
|
79
|
+
)
|
|
80
|
+
payload_to_publish = forwarded_rpc_response.model_dump(
|
|
81
|
+
by_alias=True, exclude_none=True
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
component.publish_a2a_message(
|
|
86
|
+
payload_to_publish,
|
|
87
|
+
target_topic,
|
|
88
|
+
)
|
|
89
|
+
log.debug(
|
|
90
|
+
"%s Forwarded DataPart signal for main task %s (from peer %s) to %s.",
|
|
91
|
+
component.log_identifier,
|
|
92
|
+
main_logical_task_id,
|
|
93
|
+
peer_agent_name,
|
|
94
|
+
target_topic,
|
|
95
|
+
)
|
|
96
|
+
except Exception as pub_err:
|
|
97
|
+
log.exception(
|
|
98
|
+
"%s Failed to publish forwarded status signal for main task %s: %s",
|
|
99
|
+
component.log_identifier,
|
|
100
|
+
main_logical_task_id,
|
|
101
|
+
pub_err,
|
|
102
|
+
)
|
|
103
|
+
message.call_acknowledgements()
|
|
104
|
+
|
|
51
105
|
|
|
52
106
|
def _register_peer_artifacts_in_parent_context(
|
|
53
107
|
parent_task_context: "TaskExecutionContext",
|
|
@@ -123,6 +177,30 @@ async def process_event(component, event: Event):
|
|
|
123
177
|
agent_status_sub_prefix
|
|
124
178
|
):
|
|
125
179
|
await handle_a2a_response(component, message)
|
|
180
|
+
elif hasattr(component, "trust_manager") and component.trust_manager:
|
|
181
|
+
# Check if this is a trust card message (enterprise feature)
|
|
182
|
+
try:
|
|
183
|
+
if component.trust_manager.is_trust_card_topic(topic):
|
|
184
|
+
await component.trust_manager.handle_trust_card_message(
|
|
185
|
+
message, topic
|
|
186
|
+
)
|
|
187
|
+
message.call_acknowledgements()
|
|
188
|
+
return
|
|
189
|
+
except Exception as e:
|
|
190
|
+
log.error(
|
|
191
|
+
"%s Error handling trust card message: %s",
|
|
192
|
+
component.log_identifier,
|
|
193
|
+
e,
|
|
194
|
+
)
|
|
195
|
+
message.call_acknowledgements()
|
|
196
|
+
return
|
|
197
|
+
|
|
198
|
+
log.warning(
|
|
199
|
+
"%s Received message on unhandled topic: %s",
|
|
200
|
+
component.log_identifier,
|
|
201
|
+
topic,
|
|
202
|
+
)
|
|
203
|
+
message.call_acknowledgements()
|
|
126
204
|
else:
|
|
127
205
|
log.warning(
|
|
128
206
|
"%s Received message on unhandled topic: %s",
|
|
@@ -171,7 +249,7 @@ async def process_event(component, event: Event):
|
|
|
171
249
|
|
|
172
250
|
async def _publish_peer_tool_result_notification(
|
|
173
251
|
component: "SamAgentComponent",
|
|
174
|
-
correlation_data:
|
|
252
|
+
correlation_data: dict[str, Any],
|
|
175
253
|
payload_to_queue: Any,
|
|
176
254
|
log_identifier: str,
|
|
177
255
|
):
|
|
@@ -229,12 +307,11 @@ async def handle_a2a_request(component, message: SolaceMessage):
|
|
|
229
307
|
payload_dict = message.get_payload()
|
|
230
308
|
if not isinstance(payload_dict, dict):
|
|
231
309
|
raise ValueError("Payload is not a dictionary.")
|
|
232
|
-
|
|
233
|
-
|
|
310
|
+
|
|
234
311
|
a2a_request: A2ARequest = A2ARequest.model_validate(payload_dict)
|
|
235
312
|
jsonrpc_request_id = a2a.get_request_id(a2a_request)
|
|
236
313
|
|
|
237
|
-
# Extract properties from message user properties
|
|
314
|
+
# Extract properties from message user properties
|
|
238
315
|
client_id = message.get_user_properties().get("clientId", "default_client")
|
|
239
316
|
status_topic_from_peer = message.get_user_properties().get("a2aStatusTopic")
|
|
240
317
|
reply_topic_from_peer = message.get_user_properties().get("replyTo")
|
|
@@ -248,6 +325,90 @@ async def handle_a2a_request(component, message: SolaceMessage):
|
|
|
248
325
|
# For Send, we will generate it.
|
|
249
326
|
logical_task_id = None
|
|
250
327
|
method = a2a.get_request_method(a2a_request)
|
|
328
|
+
|
|
329
|
+
# Enterprise feature: Verify user authentication if trust manager enabled
|
|
330
|
+
verified_user_identity = None
|
|
331
|
+
if hasattr(component, "trust_manager") and component.trust_manager:
|
|
332
|
+
# Determine task_id for verification
|
|
333
|
+
if method == "tasks/cancel":
|
|
334
|
+
verification_task_id = a2a.get_task_id_from_cancel_request(a2a_request)
|
|
335
|
+
elif method in ["message/send", "message/stream"]:
|
|
336
|
+
verification_task_id = str(a2a.get_request_id(a2a_request))
|
|
337
|
+
else:
|
|
338
|
+
verification_task_id = None
|
|
339
|
+
|
|
340
|
+
if verification_task_id:
|
|
341
|
+
try:
|
|
342
|
+
# Enterprise handles all verification logic
|
|
343
|
+
verified_user_identity = (
|
|
344
|
+
component.trust_manager.verify_request_authentication(
|
|
345
|
+
message=message,
|
|
346
|
+
task_id=verification_task_id,
|
|
347
|
+
namespace=namespace,
|
|
348
|
+
jsonrpc_request_id=jsonrpc_request_id,
|
|
349
|
+
)
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
if verified_user_identity:
|
|
353
|
+
log.info(
|
|
354
|
+
"%s Successfully authenticated user '%s' for task %s",
|
|
355
|
+
component.log_identifier,
|
|
356
|
+
verified_user_identity.get("user_id"),
|
|
357
|
+
verification_task_id,
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
except Exception as e:
|
|
361
|
+
# Authentication failed - enterprise provides error details
|
|
362
|
+
log.error(
|
|
363
|
+
"%s Authentication failed for task %s: %s",
|
|
364
|
+
component.log_identifier,
|
|
365
|
+
verification_task_id,
|
|
366
|
+
e,
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
# Build error response using enterprise exception data if available
|
|
370
|
+
error_data = {
|
|
371
|
+
"reason": "authentication_failed",
|
|
372
|
+
"task_id": verification_task_id,
|
|
373
|
+
}
|
|
374
|
+
if hasattr(e, "create_error_response_data"):
|
|
375
|
+
error_data = e.create_error_response_data()
|
|
376
|
+
|
|
377
|
+
error_response = a2a.create_invalid_request_error_response(
|
|
378
|
+
message="Authentication failed",
|
|
379
|
+
request_id=jsonrpc_request_id,
|
|
380
|
+
data=error_data,
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
# Determine reply topic
|
|
384
|
+
reply_topic = message.get_user_properties().get("replyTo")
|
|
385
|
+
if not reply_topic:
|
|
386
|
+
client_id = message.get_user_properties().get(
|
|
387
|
+
"clientId", "default_client"
|
|
388
|
+
)
|
|
389
|
+
reply_topic = a2a.get_client_response_topic(
|
|
390
|
+
namespace, client_id
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
component.publish_a2a_message(
|
|
394
|
+
payload=error_response.model_dump(exclude_none=True),
|
|
395
|
+
topic=reply_topic,
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
try:
|
|
399
|
+
message.call_acknowledgements()
|
|
400
|
+
log.debug(
|
|
401
|
+
"%s ACKed message with failed authentication",
|
|
402
|
+
component.log_identifier,
|
|
403
|
+
)
|
|
404
|
+
except Exception as ack_e:
|
|
405
|
+
log.error(
|
|
406
|
+
"%s Failed to ACK message after authentication failure: %s",
|
|
407
|
+
component.log_identifier,
|
|
408
|
+
ack_e,
|
|
409
|
+
)
|
|
410
|
+
return None
|
|
411
|
+
|
|
251
412
|
if method == "tasks/cancel":
|
|
252
413
|
logical_task_id = a2a.get_task_id_from_cancel_request(a2a_request)
|
|
253
414
|
log.info(
|
|
@@ -357,6 +518,35 @@ async def handle_a2a_request(component, message: SolaceMessage):
|
|
|
357
518
|
# The gateway/client is the source of truth for the task ID.
|
|
358
519
|
# The agent adopts the ID from the JSON-RPC request envelope.
|
|
359
520
|
logical_task_id = str(a2a.get_request_id(a2a_request))
|
|
521
|
+
|
|
522
|
+
try:
|
|
523
|
+
from solace_agent_mesh_enterprise.auth.input_required import (
|
|
524
|
+
a2a_auth_message_handler,
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
try:
|
|
528
|
+
message_handled = await a2a_auth_message_handler(
|
|
529
|
+
component, a2a_message, logical_task_id
|
|
530
|
+
)
|
|
531
|
+
if message_handled:
|
|
532
|
+
message.call_acknowledgements()
|
|
533
|
+
log.debug(
|
|
534
|
+
"%s ACKed message handled by input-required auth handler.",
|
|
535
|
+
component.log_identifier,
|
|
536
|
+
)
|
|
537
|
+
return None
|
|
538
|
+
except Exception as auth_import_err:
|
|
539
|
+
log.error(
|
|
540
|
+
"%s Error in input-required auth handler: %s",
|
|
541
|
+
component.log_identifier,
|
|
542
|
+
auth_import_err,
|
|
543
|
+
)
|
|
544
|
+
message.call_acknowledgements()
|
|
545
|
+
return None
|
|
546
|
+
|
|
547
|
+
except ImportError:
|
|
548
|
+
pass
|
|
549
|
+
|
|
360
550
|
# The session id is now contextId on the message
|
|
361
551
|
original_session_id = a2a_message.context_id
|
|
362
552
|
message_id = a2a_message.message_id
|
|
@@ -382,7 +572,7 @@ async def handle_a2a_request(component, message: SolaceMessage):
|
|
|
382
572
|
)
|
|
383
573
|
else:
|
|
384
574
|
session_behavior = component.default_session_behavior
|
|
385
|
-
log.
|
|
575
|
+
log.debug(
|
|
386
576
|
"%s No 'sessionBehavior' in task metadata. Using component default: '%s'.",
|
|
387
577
|
component.log_identifier,
|
|
388
578
|
session_behavior,
|
|
@@ -524,7 +714,6 @@ async def handle_a2a_request(component, message: SolaceMessage):
|
|
|
524
714
|
"is_streaming": is_streaming_request,
|
|
525
715
|
"statusTopic": status_topic_from_peer,
|
|
526
716
|
"replyToTopic": reply_topic_from_peer,
|
|
527
|
-
"original_solace_message": message,
|
|
528
717
|
"a2a_user_config": a2a_user_config,
|
|
529
718
|
"effective_session_id": effective_session_id,
|
|
530
719
|
"is_run_based_session": is_run_based_session,
|
|
@@ -537,16 +726,48 @@ async def handle_a2a_request(component, message: SolaceMessage):
|
|
|
537
726
|
"response_format": response_format,
|
|
538
727
|
"host_agent_name": agent_name,
|
|
539
728
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
a2a_context
|
|
544
|
-
|
|
729
|
+
|
|
730
|
+
# Store verified user identity claims in a2a_context (not the raw token)
|
|
731
|
+
if verified_user_identity:
|
|
732
|
+
a2a_context["verified_user_identity"] = verified_user_identity
|
|
733
|
+
log.debug(
|
|
734
|
+
"%s Stored verified user identity in a2a_context for task %s",
|
|
735
|
+
component.log_identifier,
|
|
736
|
+
logical_task_id,
|
|
737
|
+
)
|
|
738
|
+
if trace_logger.isEnabledFor(logging.DEBUG):
|
|
739
|
+
trace_logger.debug(
|
|
740
|
+
"%s A2A Context (shared service model): %s",
|
|
741
|
+
component.log_identifier,
|
|
742
|
+
a2a_context,
|
|
743
|
+
)
|
|
744
|
+
else:
|
|
745
|
+
log.debug(
|
|
746
|
+
"%s A2A Context prepared for task %s",
|
|
747
|
+
component.log_identifier,
|
|
748
|
+
a2a_context.get("logical_task_id", "unknown"),
|
|
749
|
+
)
|
|
545
750
|
|
|
546
751
|
# Create and store the execution context for this task
|
|
547
752
|
task_context = TaskExecutionContext(
|
|
548
753
|
task_id=logical_task_id, a2a_context=a2a_context
|
|
549
754
|
)
|
|
755
|
+
|
|
756
|
+
# Store the original Solace message in TaskExecutionContext instead of a2a_context
|
|
757
|
+
# This avoids serialization issues when a2a_context is stored in ADK session state
|
|
758
|
+
task_context.set_original_solace_message(message)
|
|
759
|
+
|
|
760
|
+
# Store auth token for peer delegation using generic security storage
|
|
761
|
+
if hasattr(component, "trust_manager") and component.trust_manager:
|
|
762
|
+
auth_token = message.get_user_properties().get("authToken")
|
|
763
|
+
if auth_token:
|
|
764
|
+
task_context.set_security_data("auth_token", auth_token)
|
|
765
|
+
log.debug(
|
|
766
|
+
"%s Stored authentication token in TaskExecutionContext security storage for task %s",
|
|
767
|
+
component.log_identifier,
|
|
768
|
+
logical_task_id,
|
|
769
|
+
)
|
|
770
|
+
|
|
550
771
|
with component.active_tasks_lock:
|
|
551
772
|
component.active_tasks[logical_task_id] = task_context
|
|
552
773
|
log.info(
|
|
@@ -631,7 +852,7 @@ async def handle_a2a_request(component, message: SolaceMessage):
|
|
|
631
852
|
streaming_mode = StreamingMode.SSE
|
|
632
853
|
|
|
633
854
|
max_llm_calls_per_task = component.get_config("max_llm_calls_per_task", 20)
|
|
634
|
-
log.
|
|
855
|
+
log.debug(
|
|
635
856
|
"%s Using max_llm_calls_per_task: %s",
|
|
636
857
|
component.log_identifier,
|
|
637
858
|
max_llm_calls_per_task,
|
|
@@ -797,13 +1018,13 @@ def handle_agent_card_message(component, message: SolaceMessage):
|
|
|
797
1018
|
break
|
|
798
1019
|
|
|
799
1020
|
if is_allowed:
|
|
800
|
-
|
|
1021
|
+
|
|
801
1022
|
# Also store in peer_agents for backward compatibility
|
|
802
1023
|
component.peer_agents[agent_name] = agent_card
|
|
803
1024
|
|
|
804
1025
|
# Store the agent card in the registry for health tracking
|
|
805
1026
|
is_new = component.agent_registry.add_or_update_agent(agent_card)
|
|
806
|
-
|
|
1027
|
+
|
|
807
1028
|
if is_new:
|
|
808
1029
|
log.info(
|
|
809
1030
|
"%s Registered new agent '%s' in registry.",
|
|
@@ -924,93 +1145,143 @@ async def handle_a2a_response(component, message: SolaceMessage):
|
|
|
924
1145
|
if isinstance(payload_data, TaskStatusUpdateEvent):
|
|
925
1146
|
try:
|
|
926
1147
|
status_event = payload_data
|
|
1148
|
+
|
|
927
1149
|
data_parts = a2a.get_data_parts_from_status_update(
|
|
928
1150
|
status_event
|
|
929
1151
|
)
|
|
930
1152
|
if data_parts:
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
sub_task_id,
|
|
1153
|
+
|
|
1154
|
+
peer_agent_name = (
|
|
1155
|
+
status_event.metadata.get(
|
|
1156
|
+
"agent_name", "UnknownPeer"
|
|
936
1157
|
)
|
|
937
|
-
|
|
1158
|
+
if status_event.metadata
|
|
1159
|
+
else "UnknownPeer"
|
|
1160
|
+
)
|
|
1161
|
+
|
|
1162
|
+
correlation_data = (
|
|
1163
|
+
await component._get_correlation_data_for_sub_task(
|
|
938
1164
|
sub_task_id
|
|
939
1165
|
)
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
message.call_acknowledgements()
|
|
947
|
-
return
|
|
948
|
-
|
|
949
|
-
original_task_context = correlation_data.get(
|
|
950
|
-
"original_task_context"
|
|
1166
|
+
)
|
|
1167
|
+
if not correlation_data:
|
|
1168
|
+
log.warning(
|
|
1169
|
+
"%s Correlation data not found for sub-task %s. Cannot forward status signal.",
|
|
1170
|
+
component.log_identifier,
|
|
1171
|
+
sub_task_id,
|
|
951
1172
|
)
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
"%s original_task_context not found in correlation data for sub-task %s. Cannot forward status signal.",
|
|
955
|
-
component.log_identifier,
|
|
956
|
-
sub_task_id,
|
|
957
|
-
)
|
|
958
|
-
message.call_acknowledgements()
|
|
959
|
-
return
|
|
1173
|
+
message.call_acknowledgements()
|
|
1174
|
+
return
|
|
960
1175
|
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1176
|
+
original_task_context = correlation_data.get(
|
|
1177
|
+
"original_task_context"
|
|
1178
|
+
)
|
|
1179
|
+
if not original_task_context:
|
|
1180
|
+
log.warning(
|
|
1181
|
+
"%s original_task_context not found in correlation data for sub-task %s. Cannot forward status signal.",
|
|
1182
|
+
component.log_identifier,
|
|
1183
|
+
sub_task_id,
|
|
966
1184
|
)
|
|
967
|
-
|
|
968
|
-
|
|
1185
|
+
message.call_acknowledgements()
|
|
1186
|
+
return
|
|
1187
|
+
|
|
1188
|
+
main_logical_task_id = original_task_context.get(
|
|
1189
|
+
"logical_task_id"
|
|
1190
|
+
)
|
|
1191
|
+
original_jsonrpc_request_id = original_task_context.get(
|
|
1192
|
+
"jsonrpc_request_id"
|
|
1193
|
+
)
|
|
1194
|
+
main_context_id = original_task_context.get("contextId")
|
|
1195
|
+
|
|
1196
|
+
target_topic_for_forward = original_task_context.get(
|
|
1197
|
+
"statusTopic"
|
|
1198
|
+
)
|
|
1199
|
+
|
|
1200
|
+
if (
|
|
1201
|
+
not main_logical_task_id
|
|
1202
|
+
or not original_jsonrpc_request_id
|
|
1203
|
+
or not target_topic_for_forward
|
|
1204
|
+
):
|
|
1205
|
+
log.error(
|
|
1206
|
+
"%s Missing critical info (main_task_id, original_rpc_id, or target_status_topic) in context for sub-task %s. Cannot forward. Context: %s",
|
|
1207
|
+
component.log_identifier,
|
|
1208
|
+
sub_task_id,
|
|
1209
|
+
original_task_context,
|
|
969
1210
|
)
|
|
1211
|
+
message.call_acknowledgements()
|
|
1212
|
+
return
|
|
970
1213
|
|
|
971
|
-
|
|
972
|
-
|
|
1214
|
+
event_metadata = {
|
|
1215
|
+
"agent_name": component.agent_name,
|
|
1216
|
+
"forwarded_from_peer": peer_agent_name,
|
|
1217
|
+
"original_peer_event_taskId": status_event.task_id,
|
|
1218
|
+
"original_peer_event_timestamp": (
|
|
1219
|
+
status_event.status.timestamp
|
|
1220
|
+
if status_event.status
|
|
1221
|
+
and status_event.status.timestamp
|
|
1222
|
+
else None
|
|
1223
|
+
),
|
|
1224
|
+
"function_call_id": correlation_data.get(
|
|
1225
|
+
"adk_function_call_id", None
|
|
1226
|
+
),
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
if (
|
|
1230
|
+
status_event.status.state
|
|
1231
|
+
== TaskState.input_required
|
|
1232
|
+
):
|
|
1233
|
+
log.debug(
|
|
1234
|
+
"%s Received input-required status for sub-task %s. Requesting user input. Forwarding to target.",
|
|
1235
|
+
component.log_identifier,
|
|
1236
|
+
sub_task_id,
|
|
973
1237
|
)
|
|
974
1238
|
|
|
975
1239
|
if (
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1240
|
+
status_event.metadata
|
|
1241
|
+
and "task_call_stack" in status_event.metadata
|
|
1242
|
+
and isinstance(
|
|
1243
|
+
status_event.metadata["task_call_stack"],
|
|
1244
|
+
list,
|
|
1245
|
+
)
|
|
979
1246
|
):
|
|
980
|
-
|
|
981
|
-
"
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1247
|
+
task_call_stack = status_event.metadata[
|
|
1248
|
+
"task_call_stack"
|
|
1249
|
+
].copy()
|
|
1250
|
+
task_call_stack.insert(0, sub_task_id)
|
|
1251
|
+
event_metadata["task_call_stack"] = (
|
|
1252
|
+
task_call_stack
|
|
985
1253
|
)
|
|
986
|
-
|
|
987
|
-
|
|
1254
|
+
else:
|
|
1255
|
+
event_metadata["task_call_stack"] = [
|
|
1256
|
+
sub_task_id
|
|
1257
|
+
]
|
|
1258
|
+
|
|
1259
|
+
status_event.metadata = event_metadata
|
|
1260
|
+
status_event.task_id = main_logical_task_id
|
|
1261
|
+
|
|
1262
|
+
_forward_jsonrpc_response(
|
|
1263
|
+
component=component,
|
|
1264
|
+
original_jsonrpc_request_id=original_jsonrpc_request_id,
|
|
1265
|
+
result_data=status_event,
|
|
1266
|
+
target_topic=target_topic_for_forward,
|
|
1267
|
+
main_logical_task_id=main_logical_task_id,
|
|
1268
|
+
peer_agent_name=peer_agent_name,
|
|
1269
|
+
message=message,
|
|
1270
|
+
)
|
|
1271
|
+
return
|
|
988
1272
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
else "UnknownPeer"
|
|
1273
|
+
for data_part in data_parts:
|
|
1274
|
+
log.info(
|
|
1275
|
+
"%s Received DataPart signal from peer for sub-task %s. Forwarding...",
|
|
1276
|
+
component.log_identifier,
|
|
1277
|
+
sub_task_id,
|
|
995
1278
|
)
|
|
996
1279
|
|
|
997
1280
|
forwarded_message = a2a.create_agent_parts_message(
|
|
998
1281
|
parts=[data_part],
|
|
999
|
-
metadata=
|
|
1000
|
-
"agent_name": component.agent_name,
|
|
1001
|
-
"forwarded_from_peer": peer_agent_name,
|
|
1002
|
-
"original_peer_event_taskId": status_event.task_id,
|
|
1003
|
-
"original_peer_event_timestamp": (
|
|
1004
|
-
status_event.status.timestamp
|
|
1005
|
-
if status_event.status
|
|
1006
|
-
and status_event.status.timestamp
|
|
1007
|
-
else None
|
|
1008
|
-
),
|
|
1009
|
-
"function_call_id": correlation_data.get(
|
|
1010
|
-
"adk_function_call_id", None
|
|
1011
|
-
),
|
|
1012
|
-
},
|
|
1282
|
+
metadata=event_metadata,
|
|
1013
1283
|
)
|
|
1284
|
+
|
|
1014
1285
|
forwarded_event = a2a.create_status_update(
|
|
1015
1286
|
task_id=main_logical_task_id,
|
|
1016
1287
|
context_id=main_context_id,
|
|
@@ -1024,36 +1295,15 @@ async def handle_a2a_response(component, message: SolaceMessage):
|
|
|
1024
1295
|
forwarded_event.status.timestamp = (
|
|
1025
1296
|
status_event.status.timestamp
|
|
1026
1297
|
)
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1298
|
+
_forward_jsonrpc_response(
|
|
1299
|
+
component=component,
|
|
1300
|
+
original_jsonrpc_request_id=original_jsonrpc_request_id,
|
|
1301
|
+
result_data=forwarded_event,
|
|
1302
|
+
target_topic=target_topic_for_forward,
|
|
1303
|
+
main_logical_task_id=main_logical_task_id,
|
|
1304
|
+
peer_agent_name=peer_agent_name,
|
|
1305
|
+
message=message,
|
|
1035
1306
|
)
|
|
1036
|
-
|
|
1037
|
-
try:
|
|
1038
|
-
component.publish_a2a_message(
|
|
1039
|
-
payload_to_publish,
|
|
1040
|
-
target_topic_for_forward,
|
|
1041
|
-
)
|
|
1042
|
-
log.info(
|
|
1043
|
-
"%s Forwarded DataPart signal for main task %s (from peer %s) to %s.",
|
|
1044
|
-
component.log_identifier,
|
|
1045
|
-
main_logical_task_id,
|
|
1046
|
-
peer_agent_name,
|
|
1047
|
-
target_topic_for_forward,
|
|
1048
|
-
)
|
|
1049
|
-
except Exception as pub_err:
|
|
1050
|
-
log.exception(
|
|
1051
|
-
"%s Failed to publish forwarded status signal for main task %s: %s",
|
|
1052
|
-
component.log_identifier,
|
|
1053
|
-
main_logical_task_id,
|
|
1054
|
-
pub_err,
|
|
1055
|
-
)
|
|
1056
|
-
message.call_acknowledgements()
|
|
1057
1307
|
return
|
|
1058
1308
|
|
|
1059
1309
|
payload_to_queue = status_event.model_dump(
|
|
@@ -1581,81 +1831,95 @@ def handle_sam_event(component, message, topic):
|
|
|
1581
1831
|
"""Handle incoming SAM system events."""
|
|
1582
1832
|
try:
|
|
1583
1833
|
payload = message.get_payload()
|
|
1584
|
-
|
|
1834
|
+
|
|
1585
1835
|
if not isinstance(payload, dict):
|
|
1586
1836
|
log.warning("Invalid SAM event payload - not a dict")
|
|
1587
1837
|
message.call_acknowledgements()
|
|
1588
1838
|
return
|
|
1589
|
-
|
|
1839
|
+
|
|
1590
1840
|
event_type = payload.get("event_type")
|
|
1591
1841
|
if not event_type:
|
|
1592
1842
|
log.warning("SAM event missing event_type field")
|
|
1593
1843
|
message.call_acknowledgements()
|
|
1594
1844
|
return
|
|
1595
|
-
|
|
1845
|
+
|
|
1596
1846
|
log.info("%s Received SAM event: %s", component.log_identifier, event_type)
|
|
1597
|
-
|
|
1847
|
+
|
|
1598
1848
|
if event_type == "session.deleted":
|
|
1599
1849
|
data = payload.get("data", {})
|
|
1600
1850
|
session_id = data.get("session_id")
|
|
1601
1851
|
user_id = data.get("user_id")
|
|
1602
1852
|
agent_id = data.get("agent_id")
|
|
1603
|
-
|
|
1853
|
+
|
|
1604
1854
|
if not all([session_id, user_id, agent_id]):
|
|
1605
1855
|
log.warning("Missing required fields in session.deleted event")
|
|
1606
1856
|
message.call_acknowledgements()
|
|
1607
1857
|
return
|
|
1608
|
-
|
|
1858
|
+
|
|
1609
1859
|
current_agent = component.get_config("agent_name")
|
|
1610
|
-
|
|
1860
|
+
|
|
1611
1861
|
if agent_id == current_agent:
|
|
1612
|
-
log.info(
|
|
1613
|
-
|
|
1614
|
-
|
|
1862
|
+
log.info(
|
|
1863
|
+
"%s Processing session.deleted event for session %s",
|
|
1864
|
+
component.log_identifier,
|
|
1865
|
+
session_id,
|
|
1866
|
+
)
|
|
1867
|
+
asyncio.create_task(
|
|
1868
|
+
cleanup_agent_session(component, session_id, user_id)
|
|
1869
|
+
)
|
|
1615
1870
|
else:
|
|
1616
|
-
log.debug(
|
|
1871
|
+
log.debug(
|
|
1872
|
+
"Session deletion event for different agent: %s != %s",
|
|
1873
|
+
agent_id,
|
|
1874
|
+
current_agent,
|
|
1875
|
+
)
|
|
1617
1876
|
else:
|
|
1618
1877
|
log.debug("Unhandled SAM event type: %s", event_type)
|
|
1619
|
-
|
|
1878
|
+
|
|
1620
1879
|
message.call_acknowledgements()
|
|
1621
|
-
|
|
1880
|
+
|
|
1622
1881
|
except Exception as e:
|
|
1623
1882
|
log.error("Error handling SAM event %s: %s", topic, e)
|
|
1624
1883
|
message.call_acknowledgements()
|
|
1625
1884
|
|
|
1626
1885
|
|
|
1627
|
-
|
|
1628
1886
|
async def cleanup_agent_session(component, session_id: str, user_id: str):
|
|
1629
1887
|
"""Clean up agent-side session data."""
|
|
1630
1888
|
try:
|
|
1631
1889
|
log.info("Starting cleanup for session %s, user %s", session_id, user_id)
|
|
1632
|
-
|
|
1633
|
-
if hasattr(component,
|
|
1890
|
+
|
|
1891
|
+
if hasattr(component, "session_service") and component.session_service:
|
|
1634
1892
|
agent_name = component.get_config("agent_name")
|
|
1635
|
-
log.info(
|
|
1893
|
+
log.info(
|
|
1894
|
+
"Deleting session %s from agent %s session service",
|
|
1895
|
+
session_id,
|
|
1896
|
+
agent_name,
|
|
1897
|
+
)
|
|
1636
1898
|
await component.session_service.delete_session(
|
|
1637
|
-
app_name=agent_name,
|
|
1638
|
-
user_id=user_id,
|
|
1639
|
-
session_id=session_id
|
|
1899
|
+
app_name=agent_name, user_id=user_id, session_id=session_id
|
|
1640
1900
|
)
|
|
1641
1901
|
log.info("Successfully deleted session %s from session service", session_id)
|
|
1642
1902
|
else:
|
|
1643
1903
|
log.info("No session service available for cleanup")
|
|
1644
|
-
|
|
1904
|
+
|
|
1645
1905
|
with component.active_tasks_lock:
|
|
1646
1906
|
tasks_to_cancel = []
|
|
1647
1907
|
for task_id, context in component.active_tasks.items():
|
|
1648
|
-
if (
|
|
1649
|
-
context
|
|
1908
|
+
if (
|
|
1909
|
+
hasattr(context, "a2a_context")
|
|
1910
|
+
and context.a2a_context.get("session_id") == session_id
|
|
1911
|
+
):
|
|
1650
1912
|
tasks_to_cancel.append(task_id)
|
|
1651
|
-
|
|
1913
|
+
|
|
1652
1914
|
for task_id in tasks_to_cancel:
|
|
1653
1915
|
context = component.active_tasks.get(task_id)
|
|
1654
1916
|
if context:
|
|
1655
1917
|
context.cancel()
|
|
1656
|
-
log.info(
|
|
1657
|
-
|
|
1918
|
+
log.info(
|
|
1919
|
+
"Cancelled task %s for deleted session %s", task_id, session_id
|
|
1920
|
+
)
|
|
1921
|
+
|
|
1658
1922
|
log.info("Session cleanup completed for session %s", session_id)
|
|
1659
|
-
|
|
1923
|
+
|
|
1660
1924
|
except Exception as e:
|
|
1661
1925
|
log.error("Error cleaning up session %s: %s", session_id, e)
|