solace-agent-mesh 1.0.6__py3-none-any.whl → 1.0.8__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/artifacts/__init__.py +1 -0
- solace_agent_mesh/agent/adk/{filesystem_artifact_service.py → artifacts/filesystem_artifact_service.py} +14 -15
- solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +440 -0
- solace_agent_mesh/agent/adk/callbacks.py +123 -159
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +316 -0
- solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +414 -0
- solace_agent_mesh/agent/adk/mcp_content_processor.py +665 -0
- solace_agent_mesh/agent/adk/services.py +43 -1
- solace_agent_mesh/agent/adk/setup.py +85 -45
- solace_agent_mesh/agent/adk/tool_wrapper.py +19 -3
- solace_agent_mesh/agent/protocol/event_handlers.py +1 -1
- solace_agent_mesh/agent/sac/app.py +67 -0
- solace_agent_mesh/agent/sac/component.py +14 -86
- solace_agent_mesh/assets/docs/404.html +3 -3
- solace_agent_mesh/assets/docs/assets/js/04989206.b9dfe831.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/0e682baa.b3bbde9a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/1023fc19.364235d5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/1523c6b4.1b0ec6f9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/166ab619.e8f3a7c7.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/21ceee5f.3bf39250.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3d406171.7d02a73b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/42b3f8d8.8ccb9901.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/442a8107.b3159bb2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4c2787c2.fc6804f2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5b4258a4.0d080cd9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/75384d09.ccd480c4.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/768e31b0.8b51cd70.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/945fb41e.c63791d1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{9eff14a2.036c35ea.js → 9eff14a2.472b0310.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/a3a92b25.4b7fa6a2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/aba87c2f.76376d7c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ae4415af.7a2f0bbf.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/b7006a3a.73a79653.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/beecea0d.ae31f6a7.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c2c06897.587b4af5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{cd3d4052.ca6eed8c.js → cd3d4052.b6535013.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.731836ad.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f897a61a.0aa29dbb.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.6dba4a66.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.6415ad00.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +28 -4
- solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/concepts/cli/index.html +8 -8
- solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +5 -5
- solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +5 -5
- solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +34 -5
- solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +5 -5
- solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/index.html +72 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +5 -5
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +7 -7
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +35 -16
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/bedrock-agents/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/custom-agent/index.html +17 -11
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/event-mesh-gateway/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/mcp-integration/index.html +5 -5
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/mongodb-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/rag-integration/index.html +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/rest-gateway/index.html +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/sql-database/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/artifact-management/index.html +8 -8
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/audio-tools/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/data-analysis-tools/index.html +8 -8
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/embeds/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/index.html +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-agents/index.html +35 -23
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-gateways/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +4 -4
- solace_agent_mesh/assets/docs/lunr-index-1756153049706.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1756153049706.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/cli/commands/add_cmd/add_cmd_llm.txt +1 -1
- solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +67 -10
- solace_agent_mesh/cli/commands/add_cmd/gateway_cmd.py +2 -2
- solace_agent_mesh/cli/commands/eval_cmd.py +8 -2
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +20 -2
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +25 -1
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +45 -1
- solace_agent_mesh/cli/utils.py +21 -12
- solace_agent_mesh/client/webui/frontend/static/assets/main-BucUdn9m.js +673 -0
- solace_agent_mesh/client/webui/frontend/static/index.html +1 -1
- solace_agent_mesh/common/a2a_protocol.py +1 -1
- solace_agent_mesh/common/utils/mime_helpers.py +60 -1
- solace_agent_mesh/config_portal/backend/server.py +1 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/{_index-xSu2leR8.js → _index-MqsrTd6g.js} +9 -9
- solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-950eb3be.js → manifest-28271392.js} +1 -1
- solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
- solace_agent_mesh/core_a2a/core_a2a_llm.txt +1 -1
- solace_agent_mesh/core_a2a/service.py +1 -1
- solace_agent_mesh/evaluation/run.py +149 -15
- solace_agent_mesh/evaluation/summary_builder.py +5 -3
- solace_agent_mesh/gateway/http_sse/dependencies.py +1 -1
- solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +1 -1
- solace_agent_mesh/gateway/http_sse/services/task_service.py +1 -1
- solace_agent_mesh/llm_detail.txt +2 -2
- solace_agent_mesh/templates/agent_template.yaml +1 -1
- solace_agent_mesh/templates/plugin_agent_config_template.yaml +3 -3
- solace_agent_mesh/templates/plugin_readme_template.md +1 -1
- solace_agent_mesh/templates/shared_config.yaml +8 -1
- {solace_agent_mesh-1.0.6.dist-info → solace_agent_mesh-1.0.8.dist-info}/METADATA +4 -1
- {solace_agent_mesh-1.0.6.dist-info → solace_agent_mesh-1.0.8.dist-info}/RECORD +113 -108
- solace_agent_mesh/assets/docs/assets/js/04989206.da8246cd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/0e682baa.79f0ab22.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/1023fc19.8e6d174c.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/1523c6b4.91c7bc01.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/166ab619.7d97ccaf.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/21ceee5f.614fa8dd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3d406171.9b081d5f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/42b3f8d8.36090198.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/442a8107.5ba94b65.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/4c2787c2.66ee00e9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5b4258a4.bda20761.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/75384d09.c3991823.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/768e31b0.a12673db.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/945fb41e.74d728aa.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a3a92b25.26ca071f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/aba87c2f.a6b84da6.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ae4415af.96189a93.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/b7006a3a.38c0cf3d.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/bb2ef573.56931473.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c2c06897.63b76e9e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.5aff74ab.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f897a61a.862b0514.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.ea9672b6.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.aa687c82.js +0 -1
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +0 -17
- solace_agent_mesh/assets/docs/lunr-index-1755285974624.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1755285974624.json +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-DzKPMTRs.js +0 -673
- /solace_agent_mesh/assets/docs/assets/js/{main.ea9672b6.js.LICENSE.txt → main.6dba4a66.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.0.6.dist-info → solace_agent_mesh-1.0.8.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.0.6.dist-info → solace_agent_mesh-1.0.8.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.0.6.dist-info → solace_agent_mesh-1.0.8.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Intelligent MCP Callback Functions
|
|
3
|
+
|
|
4
|
+
This module contains the refactored MCP callback functions that use intelligent
|
|
5
|
+
content processing to save MCP tool responses as appropriately typed artifacts.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import uuid
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
from typing import Any, Dict, TYPE_CHECKING, List, Optional
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from pydantic import BaseModel
|
|
14
|
+
|
|
15
|
+
from google.adk.tools import ToolContext, BaseTool
|
|
16
|
+
from solace_ai_connector.common.log import log
|
|
17
|
+
|
|
18
|
+
from .mcp_content_processor import MCPContentProcessor, MCPContentProcessorConfig
|
|
19
|
+
from ...agent.utils.artifact_helpers import (
|
|
20
|
+
save_artifact_with_metadata,
|
|
21
|
+
DEFAULT_SCHEMA_MAX_KEYS,
|
|
22
|
+
)
|
|
23
|
+
from ...agent.utils.context_helpers import get_original_session_id
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from ...agent.sac.component import SamAgentComponent
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class McpSaveStatus(str, Enum):
|
|
31
|
+
"""Enumeration for the status of an MCP save operation."""
|
|
32
|
+
|
|
33
|
+
SUCCESS = "success"
|
|
34
|
+
PARTIAL_SUCCESS = "partial_success"
|
|
35
|
+
ERROR = "error"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class SavedArtifactInfo(BaseModel):
|
|
39
|
+
"""
|
|
40
|
+
A Pydantic model to hold the details of a successfully saved artifact.
|
|
41
|
+
This mirrors the dictionary structure returned by save_artifact_with_metadata.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
status: str
|
|
45
|
+
data_filename: str
|
|
46
|
+
data_version: int
|
|
47
|
+
metadata_filename: str
|
|
48
|
+
metadata_version: int
|
|
49
|
+
message: str
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class McpSaveResult(BaseModel):
|
|
53
|
+
"""
|
|
54
|
+
The definitive, type-safe result of an MCP response save operation.
|
|
55
|
+
|
|
56
|
+
Attributes:
|
|
57
|
+
status: The overall status of the save operation.
|
|
58
|
+
message: A human-readable summary of the outcome.
|
|
59
|
+
artifacts_saved: A list of successfully created "intelligent" artifacts.
|
|
60
|
+
fallback_artifact: An optional artifact representing the raw JSON response,
|
|
61
|
+
created only if intelligent processing failed.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
status: McpSaveStatus
|
|
65
|
+
message: str
|
|
66
|
+
artifacts_saved: List[SavedArtifactInfo] = []
|
|
67
|
+
fallback_artifact: Optional[SavedArtifactInfo] = None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
async def save_mcp_response_as_artifact_intelligent(
|
|
71
|
+
tool: BaseTool,
|
|
72
|
+
tool_context: ToolContext,
|
|
73
|
+
host_component: "SamAgentComponent",
|
|
74
|
+
mcp_response_dict: Dict[str, Any],
|
|
75
|
+
original_tool_args: Dict[str, Any],
|
|
76
|
+
) -> McpSaveResult:
|
|
77
|
+
"""
|
|
78
|
+
Intelligently processes and saves MCP tool response content as typed artifacts.
|
|
79
|
+
|
|
80
|
+
This function uses intelligent content processing to:
|
|
81
|
+
- Detect and parse different content types (text, image, audio, resource)
|
|
82
|
+
- Create appropriately typed artifacts with proper MIME types
|
|
83
|
+
- Generate enhanced metadata based on content analysis
|
|
84
|
+
- Fall back to raw JSON saving if intelligent processing fails
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
tool: The MCPTool instance that generated the response.
|
|
88
|
+
tool_context: The ADK ToolContext.
|
|
89
|
+
host_component: The A2A_ADK_HostComponent instance for accessing config and services.
|
|
90
|
+
mcp_response_dict: The raw MCP tool response dictionary.
|
|
91
|
+
original_tool_args: The original arguments passed to the MCP tool.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
An McpSaveResult object containing the structured result of the operation,
|
|
95
|
+
including status, a list of successfully saved artifacts, and any
|
|
96
|
+
fallback artifact.
|
|
97
|
+
"""
|
|
98
|
+
log_identifier = f"[IntelligentMCPCallback:{tool.name}]"
|
|
99
|
+
log.debug("%s Starting intelligent MCP response artifact saving...", log_identifier)
|
|
100
|
+
|
|
101
|
+
processor_config_dict = host_component.get_config("mcp_intelligent_processing", {})
|
|
102
|
+
processor_config = MCPContentProcessorConfig.from_dict(processor_config_dict)
|
|
103
|
+
|
|
104
|
+
saved_artifacts: List[SavedArtifactInfo] = []
|
|
105
|
+
failed_artifacts: List[Dict[str, Any]] = []
|
|
106
|
+
fallback_artifact: Optional[SavedArtifactInfo] = None
|
|
107
|
+
overall_status = McpSaveStatus.SUCCESS
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
if not processor_config.enable_intelligent_processing:
|
|
111
|
+
log.info(
|
|
112
|
+
"%s Intelligent processing disabled, using raw JSON fallback.",
|
|
113
|
+
log_identifier,
|
|
114
|
+
)
|
|
115
|
+
fallback_dict = await _save_raw_mcp_response_fallback(
|
|
116
|
+
tool,
|
|
117
|
+
tool_context,
|
|
118
|
+
host_component,
|
|
119
|
+
mcp_response_dict,
|
|
120
|
+
original_tool_args,
|
|
121
|
+
)
|
|
122
|
+
if fallback_dict.get("status") in ["success", "partial_success"]:
|
|
123
|
+
fallback_artifact = SavedArtifactInfo(**fallback_dict)
|
|
124
|
+
status = McpSaveStatus.SUCCESS
|
|
125
|
+
else:
|
|
126
|
+
status = McpSaveStatus.ERROR
|
|
127
|
+
return McpSaveResult(
|
|
128
|
+
status=status,
|
|
129
|
+
message="Intelligent processing disabled; saved raw JSON as fallback.",
|
|
130
|
+
fallback_artifact=fallback_artifact,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
processor = MCPContentProcessor(tool.name, original_tool_args)
|
|
134
|
+
content_items = processor.process_mcp_response(mcp_response_dict)
|
|
135
|
+
|
|
136
|
+
if not content_items:
|
|
137
|
+
log.warning(
|
|
138
|
+
"%s No content items found, falling back to raw JSON.", log_identifier
|
|
139
|
+
)
|
|
140
|
+
fallback_dict = await _save_raw_mcp_response_fallback(
|
|
141
|
+
tool,
|
|
142
|
+
tool_context,
|
|
143
|
+
host_component,
|
|
144
|
+
mcp_response_dict,
|
|
145
|
+
original_tool_args,
|
|
146
|
+
)
|
|
147
|
+
if fallback_dict.get("status") in ["success", "partial_success"]:
|
|
148
|
+
fallback_artifact = SavedArtifactInfo(**fallback_dict)
|
|
149
|
+
return McpSaveResult(
|
|
150
|
+
status=McpSaveStatus.PARTIAL_SUCCESS,
|
|
151
|
+
message="No content items found in MCP response; saved raw JSON as fallback.",
|
|
152
|
+
fallback_artifact=fallback_artifact,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
log.info(
|
|
156
|
+
"%s Processing %d content items intelligently.",
|
|
157
|
+
log_identifier,
|
|
158
|
+
len(content_items),
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
for item in content_items:
|
|
162
|
+
try:
|
|
163
|
+
if hasattr(item, "uri"):
|
|
164
|
+
item.uri = str(item.uri)
|
|
165
|
+
result_dict = await _save_content_item_as_artifact(
|
|
166
|
+
item, tool_context, host_component
|
|
167
|
+
)
|
|
168
|
+
if result_dict.get("status") in ["success", "partial_success"]:
|
|
169
|
+
saved_artifacts.append(SavedArtifactInfo(**result_dict))
|
|
170
|
+
else:
|
|
171
|
+
log.warning(
|
|
172
|
+
"%s Failed to save content item: %s",
|
|
173
|
+
log_identifier,
|
|
174
|
+
result_dict.get("message", "Unknown error"),
|
|
175
|
+
)
|
|
176
|
+
overall_status = McpSaveStatus.PARTIAL_SUCCESS
|
|
177
|
+
failed_artifacts.append(result_dict)
|
|
178
|
+
except Exception as e:
|
|
179
|
+
if not processor_config.fallback_to_raw_on_error:
|
|
180
|
+
raise
|
|
181
|
+
log.exception("%s Error saving content item: %s", log_identifier, e)
|
|
182
|
+
overall_status = McpSaveStatus.PARTIAL_SUCCESS
|
|
183
|
+
failed_artifacts.append({"status": "error", "message": str(e)})
|
|
184
|
+
|
|
185
|
+
if not saved_artifacts:
|
|
186
|
+
if failed_artifacts:
|
|
187
|
+
first_error_msg = failed_artifacts[0].get("message", "Unknown error")
|
|
188
|
+
log.warning(
|
|
189
|
+
"%s No items saved successfully. First error: %s",
|
|
190
|
+
log_identifier,
|
|
191
|
+
first_error_msg,
|
|
192
|
+
)
|
|
193
|
+
return McpSaveResult(
|
|
194
|
+
status=McpSaveStatus.ERROR,
|
|
195
|
+
message=f"Content processing failed. First error: {first_error_msg}",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
fallback_dict = await _save_raw_mcp_response_fallback(
|
|
199
|
+
tool,
|
|
200
|
+
tool_context,
|
|
201
|
+
host_component,
|
|
202
|
+
mcp_response_dict,
|
|
203
|
+
original_tool_args,
|
|
204
|
+
)
|
|
205
|
+
if fallback_dict.get("status") in ["success", "partial_success"]:
|
|
206
|
+
fallback_artifact = SavedArtifactInfo(**fallback_dict)
|
|
207
|
+
return McpSaveResult(
|
|
208
|
+
status=McpSaveStatus.PARTIAL_SUCCESS,
|
|
209
|
+
message="Content processing failed for all items; saved raw JSON as fallback.",
|
|
210
|
+
fallback_artifact=fallback_artifact,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
if processor_config_dict.get("save_raw_alongside_intelligent", False):
|
|
214
|
+
try:
|
|
215
|
+
fallback_dict = await _save_raw_mcp_response_fallback(
|
|
216
|
+
tool,
|
|
217
|
+
tool_context,
|
|
218
|
+
host_component,
|
|
219
|
+
mcp_response_dict,
|
|
220
|
+
original_tool_args,
|
|
221
|
+
)
|
|
222
|
+
if fallback_dict.get("status") in ["success", "partial_success"]:
|
|
223
|
+
fallback_artifact = SavedArtifactInfo(**fallback_dict)
|
|
224
|
+
except Exception as e:
|
|
225
|
+
log.warning(
|
|
226
|
+
"%s Failed to save raw JSON alongside: %s", log_identifier, e
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
log.info(
|
|
230
|
+
"%s Intelligent processing complete: %d artifacts saved, status: %s",
|
|
231
|
+
log_identifier,
|
|
232
|
+
len(saved_artifacts),
|
|
233
|
+
overall_status.value,
|
|
234
|
+
)
|
|
235
|
+
return McpSaveResult(
|
|
236
|
+
status=overall_status,
|
|
237
|
+
artifacts_saved=saved_artifacts,
|
|
238
|
+
fallback_artifact=fallback_artifact,
|
|
239
|
+
message=f"Successfully processed {len(saved_artifacts)} content items.",
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
except Exception as e:
|
|
243
|
+
log.exception(
|
|
244
|
+
"%s Error in intelligent MCP response processing: %s", log_identifier, e
|
|
245
|
+
)
|
|
246
|
+
if processor_config.fallback_to_raw_on_error:
|
|
247
|
+
log.info(
|
|
248
|
+
"%s Falling back to raw JSON due to processing error.", log_identifier
|
|
249
|
+
)
|
|
250
|
+
try:
|
|
251
|
+
fallback_dict = await _save_raw_mcp_response_fallback(
|
|
252
|
+
tool,
|
|
253
|
+
tool_context,
|
|
254
|
+
host_component,
|
|
255
|
+
mcp_response_dict,
|
|
256
|
+
original_tool_args,
|
|
257
|
+
)
|
|
258
|
+
if fallback_dict.get("status") in ["success", "partial_success"]:
|
|
259
|
+
fallback_artifact = SavedArtifactInfo(**fallback_dict)
|
|
260
|
+
return McpSaveResult(
|
|
261
|
+
status=McpSaveStatus.PARTIAL_SUCCESS,
|
|
262
|
+
artifacts_saved=saved_artifacts,
|
|
263
|
+
fallback_artifact=fallback_artifact,
|
|
264
|
+
message=f"Intelligent processing failed, saved raw JSON as fallback: {e}",
|
|
265
|
+
)
|
|
266
|
+
except Exception as fallback_error:
|
|
267
|
+
log.exception(
|
|
268
|
+
"%s Fallback also failed: %s", log_identifier, fallback_error
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
return McpSaveResult(
|
|
272
|
+
status=McpSaveStatus.ERROR,
|
|
273
|
+
artifacts_saved=saved_artifacts,
|
|
274
|
+
fallback_artifact=None,
|
|
275
|
+
message=f"Failed to save MCP response as artifact: {e}",
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
async def _save_content_item_as_artifact(
|
|
280
|
+
content_item,
|
|
281
|
+
tool_context: ToolContext,
|
|
282
|
+
host_component: "SamAgentComponent",
|
|
283
|
+
) -> Dict[str, Any]:
|
|
284
|
+
"""Save a single processed content item as an artifact."""
|
|
285
|
+
|
|
286
|
+
log_identifier = f"[IntelligentMCPCallback:SaveContentItem:{content_item.filename}]"
|
|
287
|
+
|
|
288
|
+
try:
|
|
289
|
+
artifact_service = host_component.artifact_service
|
|
290
|
+
if not artifact_service:
|
|
291
|
+
raise ValueError("ArtifactService is not available on host_component.")
|
|
292
|
+
|
|
293
|
+
app_name = host_component.agent_name
|
|
294
|
+
user_id = tool_context._invocation_context.user_id
|
|
295
|
+
session_id = get_original_session_id(tool_context._invocation_context)
|
|
296
|
+
schema_max_keys = host_component.get_config(
|
|
297
|
+
"schema_max_keys", DEFAULT_SCHEMA_MAX_KEYS
|
|
298
|
+
)
|
|
299
|
+
artifact_timestamp = datetime.now(timezone.utc)
|
|
300
|
+
|
|
301
|
+
log.debug(
|
|
302
|
+
"%s Saving content item: type=%s, mime_type=%s, size=%d bytes",
|
|
303
|
+
log_identifier,
|
|
304
|
+
content_item.content_type,
|
|
305
|
+
content_item.mime_type,
|
|
306
|
+
len(content_item.content_bytes),
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
save_result = await save_artifact_with_metadata(
|
|
310
|
+
artifact_service=artifact_service,
|
|
311
|
+
app_name=app_name,
|
|
312
|
+
user_id=user_id,
|
|
313
|
+
session_id=session_id,
|
|
314
|
+
filename=content_item.filename,
|
|
315
|
+
content_bytes=content_item.content_bytes,
|
|
316
|
+
mime_type=content_item.mime_type,
|
|
317
|
+
metadata_dict=content_item.metadata,
|
|
318
|
+
timestamp=artifact_timestamp,
|
|
319
|
+
schema_max_keys=schema_max_keys,
|
|
320
|
+
tool_context=tool_context,
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
log.info(
|
|
324
|
+
"%s Content item saved as artifact '%s' (version %s). Status: %s",
|
|
325
|
+
log_identifier,
|
|
326
|
+
save_result.get("data_filename", content_item.filename),
|
|
327
|
+
save_result.get("data_version", "N/A"),
|
|
328
|
+
save_result.get("status"),
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
return save_result
|
|
332
|
+
|
|
333
|
+
except Exception as e:
|
|
334
|
+
log.exception("%s Error saving content item as artifact: %s", log_identifier, e)
|
|
335
|
+
return {
|
|
336
|
+
"status": "error",
|
|
337
|
+
"data_filename": content_item.filename,
|
|
338
|
+
"message": f"Failed to save content item as artifact: {e}",
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
async def _save_raw_mcp_response_fallback(
|
|
343
|
+
tool: BaseTool,
|
|
344
|
+
tool_context: ToolContext,
|
|
345
|
+
host_component: "SamAgentComponent",
|
|
346
|
+
mcp_response_dict: Dict[str, Any],
|
|
347
|
+
original_tool_args: Dict[str, Any],
|
|
348
|
+
) -> Dict[str, Any]:
|
|
349
|
+
"""
|
|
350
|
+
Fallback function to save the raw MCP response as a JSON artifact.
|
|
351
|
+
This is the original behavior, used when intelligent processing is disabled or fails.
|
|
352
|
+
"""
|
|
353
|
+
log_identifier = f"[IntelligentMCPCallback:{tool.name}:RawFallback]"
|
|
354
|
+
log.debug("%s Saving raw MCP response as JSON artifact...", log_identifier)
|
|
355
|
+
|
|
356
|
+
try:
|
|
357
|
+
a2a_context = tool_context.state.get("a2a_context", {})
|
|
358
|
+
logical_task_id = a2a_context.get("logical_task_id", "unknownTask")
|
|
359
|
+
task_id_suffix = logical_task_id[-6:]
|
|
360
|
+
random_suffix = uuid.uuid4().hex[:6]
|
|
361
|
+
filename = f"{task_id_suffix}_{tool.name}_raw_{random_suffix}.json"
|
|
362
|
+
|
|
363
|
+
content_bytes = json.dumps(mcp_response_dict, indent=2).encode("utf-8")
|
|
364
|
+
mime_type = "application/json"
|
|
365
|
+
artifact_timestamp = datetime.now(timezone.utc)
|
|
366
|
+
|
|
367
|
+
metadata_for_saving = {
|
|
368
|
+
"description": f"Raw JSON response from MCP tool {tool.name}",
|
|
369
|
+
"source_tool_name": tool.name,
|
|
370
|
+
"source_tool_args": original_tool_args,
|
|
371
|
+
"processing_type": "raw_fallback",
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
artifact_service = host_component.artifact_service
|
|
375
|
+
app_name = host_component.agent_name
|
|
376
|
+
user_id = tool_context._invocation_context.user_id
|
|
377
|
+
session_id = get_original_session_id(tool_context._invocation_context)
|
|
378
|
+
schema_max_keys = host_component.get_config(
|
|
379
|
+
"schema_max_keys", DEFAULT_SCHEMA_MAX_KEYS
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
save_result = await save_artifact_with_metadata(
|
|
383
|
+
artifact_service=artifact_service,
|
|
384
|
+
app_name=app_name,
|
|
385
|
+
user_id=user_id,
|
|
386
|
+
session_id=session_id,
|
|
387
|
+
filename=filename,
|
|
388
|
+
content_bytes=content_bytes,
|
|
389
|
+
mime_type=mime_type,
|
|
390
|
+
metadata_dict=metadata_for_saving,
|
|
391
|
+
timestamp=artifact_timestamp,
|
|
392
|
+
schema_max_keys=schema_max_keys,
|
|
393
|
+
tool_context=tool_context,
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
log.info(
|
|
397
|
+
"%s Raw MCP response saved as artifact '%s' (version %s). Status: %s",
|
|
398
|
+
log_identifier,
|
|
399
|
+
save_result.get("data_filename", filename),
|
|
400
|
+
save_result.get("data_version", "N/A"),
|
|
401
|
+
save_result.get("status"),
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
return save_result
|
|
405
|
+
|
|
406
|
+
except Exception as e:
|
|
407
|
+
log.exception(
|
|
408
|
+
"%s Error saving raw MCP response as artifact: %s", log_identifier, e
|
|
409
|
+
)
|
|
410
|
+
return {
|
|
411
|
+
"status": "error",
|
|
412
|
+
"data_filename": filename if "filename" in locals() else "unknown_filename",
|
|
413
|
+
"message": f"Failed to save raw MCP response as artifact: {e}",
|
|
414
|
+
}
|