solace-agent-mesh 1.0.6__py3-none-any.whl → 1.0.7__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 +35 -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.d79f063b.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-1756146501924.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1756146501924.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.7.dist-info}/METADATA +4 -1
- {solace_agent_mesh-1.0.6.dist-info → solace_agent_mesh-1.0.7.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.d79f063b.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.0.6.dist-info → solace_agent_mesh-1.0.7.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.0.6.dist-info → solace_agent_mesh-1.0.7.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.0.6.dist-info → solace_agent_mesh-1.0.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -22,6 +22,10 @@ from ...common.a2a_protocol import (
|
|
|
22
22
|
from google.genai import types as adk_types
|
|
23
23
|
from google.adk.tools.mcp_tool import MCPTool
|
|
24
24
|
from solace_ai_connector.common.log import log
|
|
25
|
+
from .intelligent_mcp_callbacks import (
|
|
26
|
+
save_mcp_response_as_artifact_intelligent,
|
|
27
|
+
McpSaveStatus,
|
|
28
|
+
)
|
|
25
29
|
|
|
26
30
|
from ...agent.utils.artifact_helpers import (
|
|
27
31
|
METADATA_SUFFIX,
|
|
@@ -212,6 +216,7 @@ async def process_artifact_blocks_callback(
|
|
|
212
216
|
original_func=_internal_create_artifact,
|
|
213
217
|
tool_config=None, # No specific config for this internal tool
|
|
214
218
|
tool_name="_internal_create_artifact",
|
|
219
|
+
origin="internal",
|
|
215
220
|
)
|
|
216
221
|
save_result = await wrapped_creator(**kwargs_for_call)
|
|
217
222
|
|
|
@@ -451,102 +456,40 @@ def repair_history_callback(
|
|
|
451
456
|
return None
|
|
452
457
|
|
|
453
458
|
|
|
454
|
-
|
|
455
|
-
tool: BaseTool,
|
|
456
|
-
tool_context: ToolContext,
|
|
457
|
-
host_component: "SamAgentComponent",
|
|
458
|
-
mcp_response_dict: Dict[str, Any],
|
|
459
|
-
original_tool_args: Dict[str, Any],
|
|
460
|
-
) -> Dict[str, Any]:
|
|
459
|
+
def _recursively_clean_pydantic_types(data: Any) -> Any:
|
|
461
460
|
"""
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
tool: The MCPTool instance that generated the response.
|
|
466
|
-
tool_context: The ADK ToolContext.
|
|
467
|
-
host_component: The A2A_ADK_HostComponent instance for accessing config and services.
|
|
468
|
-
mcp_response_dict: The raw MCP tool response dictionary.
|
|
469
|
-
original_tool_args: The original arguments passed to the MCP tool.
|
|
470
|
-
|
|
471
|
-
Returns:
|
|
472
|
-
A dictionary containing details of the saved artifact (filename, version, etc.),
|
|
473
|
-
as returned by `save_artifact_with_metadata`.
|
|
461
|
+
Recursively traverses a data structure (dicts, lists) and converts
|
|
462
|
+
Pydantic-specific types like AnyUrl to their primitive string representation
|
|
463
|
+
to ensure JSON serializability.
|
|
474
464
|
"""
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
try:
|
|
479
|
-
a2a_context = tool_context.state.get("a2a_context", {})
|
|
480
|
-
logical_task_id = a2a_context.get("logical_task_id", "unknownTask")
|
|
481
|
-
task_id_suffix = logical_task_id[-6:]
|
|
482
|
-
random_suffix = uuid.uuid4().hex[:6]
|
|
483
|
-
filename = f"{task_id_suffix}_{tool.name}_{random_suffix}.json"
|
|
484
|
-
log.debug("%s Generated artifact filename: %s", log_identifier, filename)
|
|
485
|
-
|
|
486
|
-
content_bytes = json.dumps(mcp_response_dict, indent=2).encode("utf-8")
|
|
487
|
-
mime_type = "application/json"
|
|
488
|
-
artifact_timestamp = datetime.now(timezone.utc)
|
|
489
|
-
|
|
490
|
-
metadata_for_saving = {
|
|
491
|
-
"description": f"Full JSON response from MCP tool {tool.name}.",
|
|
492
|
-
"source_tool_name": tool.name,
|
|
493
|
-
"source_tool_args": original_tool_args,
|
|
465
|
+
if isinstance(data, dict):
|
|
466
|
+
return {
|
|
467
|
+
key: _recursively_clean_pydantic_types(value) for key, value in data.items()
|
|
494
468
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
app_name = host_component.agent_name
|
|
502
|
-
user_id = tool_context._invocation_context.user_id
|
|
503
|
-
session_id = get_original_session_id(tool_context._invocation_context)
|
|
504
|
-
schema_max_keys = host_component.get_config(
|
|
505
|
-
"schema_max_keys", DEFAULT_SCHEMA_MAX_KEYS
|
|
506
|
-
)
|
|
469
|
+
elif isinstance(data, list):
|
|
470
|
+
return [_recursively_clean_pydantic_types(item) for item in data]
|
|
471
|
+
# Check for Pydantic's AnyUrl without a direct import to avoid dependency issues.
|
|
472
|
+
elif type(data).__name__ == "AnyUrl" and hasattr(data, "__str__"):
|
|
473
|
+
return str(data)
|
|
474
|
+
return data
|
|
507
475
|
|
|
508
|
-
log.debug(
|
|
509
|
-
"%s Calling save_artifact_with_metadata with: app_name=%s, user_id=%s, session_id=%s, filename=%s, schema_max_keys=%d",
|
|
510
|
-
log_identifier,
|
|
511
|
-
app_name,
|
|
512
|
-
user_id,
|
|
513
|
-
session_id,
|
|
514
|
-
filename,
|
|
515
|
-
schema_max_keys,
|
|
516
|
-
)
|
|
517
476
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
mime_type=mime_type,
|
|
526
|
-
metadata_dict=metadata_for_saving,
|
|
527
|
-
timestamp=artifact_timestamp,
|
|
528
|
-
schema_max_keys=schema_max_keys,
|
|
529
|
-
tool_context=tool_context,
|
|
530
|
-
)
|
|
477
|
+
def _mcp_response_contains_non_text(mcp_response_dict: Dict[str, Any]) -> bool:
|
|
478
|
+
"""
|
|
479
|
+
Checks if the 'content' list in an MCP response dictionary contains any
|
|
480
|
+
items that are not of type 'text'.
|
|
481
|
+
"""
|
|
482
|
+
if not isinstance(mcp_response_dict, dict):
|
|
483
|
+
return False
|
|
531
484
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
save_result.get("data_filename", filename),
|
|
536
|
-
save_result.get("data_version", "N/A"),
|
|
537
|
-
save_result.get("status"),
|
|
538
|
-
)
|
|
539
|
-
return save_result
|
|
485
|
+
content_list = mcp_response_dict.get("content")
|
|
486
|
+
if not isinstance(content_list, list):
|
|
487
|
+
return False
|
|
540
488
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
return {
|
|
546
|
-
"status": "error",
|
|
547
|
-
"data_filename": filename if "filename" in locals() else "unknown_filename",
|
|
548
|
-
"message": f"Failed to save MCP response as artifact: {e}",
|
|
549
|
-
}
|
|
489
|
+
for item in content_list:
|
|
490
|
+
if isinstance(item, dict) and item.get("type") != "text":
|
|
491
|
+
return True
|
|
492
|
+
return False
|
|
550
493
|
|
|
551
494
|
|
|
552
495
|
async def manage_large_mcp_tool_responses_callback(
|
|
@@ -557,9 +500,24 @@ async def manage_large_mcp_tool_responses_callback(
|
|
|
557
500
|
host_component: "SamAgentComponent",
|
|
558
501
|
) -> Optional[Dict[str, Any]]:
|
|
559
502
|
"""
|
|
560
|
-
Manages large responses from MCP tools
|
|
561
|
-
|
|
562
|
-
|
|
503
|
+
Manages large or non-textual responses from MCP tools.
|
|
504
|
+
|
|
505
|
+
This callback intercepts the response from an MCPTool. Based on the response's
|
|
506
|
+
size and content type, it performs one or more of the following actions:
|
|
507
|
+
1. **Saves as Artifact:** If the response size exceeds a configured threshold,
|
|
508
|
+
or if it contains non-textual content (like images), it calls the
|
|
509
|
+
`save_mcp_response_as_artifact_intelligent` function to save the
|
|
510
|
+
response as one or more typed artifacts.
|
|
511
|
+
2. **Truncates for LLM:** If the response size exceeds a configured limit for
|
|
512
|
+
the LLM, it truncates the content to a preview string.
|
|
513
|
+
3. **Constructs Final Response:** It builds a new dictionary to be returned
|
|
514
|
+
to the LLM, which includes:
|
|
515
|
+
- A `message_to_llm` summarizing what was done (e.g., saved, truncated).
|
|
516
|
+
- `saved_mcp_response_artifact_details` with the result of the save operation.
|
|
517
|
+
- `mcp_tool_output` containing either the original response or the truncated preview.
|
|
518
|
+
- A `status` field indicating the outcome (e.g., 'processed_and_saved').
|
|
519
|
+
|
|
520
|
+
The `tool_response` is the direct output from the tool's `run_async` method.
|
|
563
521
|
"""
|
|
564
522
|
log_identifier = f"[Callback:ManageLargeMCPResponse:{tool.name}]"
|
|
565
523
|
log.info(
|
|
@@ -601,6 +559,10 @@ async def manage_large_mcp_tool_responses_callback(
|
|
|
601
559
|
)
|
|
602
560
|
mcp_response_dict = tool_response
|
|
603
561
|
|
|
562
|
+
# Clean any Pydantic-specific types before serialization
|
|
563
|
+
mcp_response_dict = _recursively_clean_pydantic_types(mcp_response_dict)
|
|
564
|
+
cleaned_args = _recursively_clean_pydantic_types(args)
|
|
565
|
+
|
|
604
566
|
try:
|
|
605
567
|
save_threshold = host_component.get_config(
|
|
606
568
|
"mcp_tool_response_save_threshold_bytes", 2048
|
|
@@ -619,53 +581,43 @@ async def manage_large_mcp_tool_responses_callback(
|
|
|
619
581
|
save_threshold = 2048
|
|
620
582
|
llm_max_bytes = 4096
|
|
621
583
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
584
|
+
contains_non_text_content = _mcp_response_contains_non_text(mcp_response_dict)
|
|
585
|
+
if not contains_non_text_content:
|
|
586
|
+
try:
|
|
587
|
+
serialized_original_response_str = json.dumps(mcp_response_dict)
|
|
588
|
+
original_response_bytes = len(
|
|
589
|
+
serialized_original_response_str.encode("utf-8")
|
|
590
|
+
)
|
|
591
|
+
log.debug(
|
|
592
|
+
"%s Original response size: %d bytes.",
|
|
593
|
+
log_identifier,
|
|
594
|
+
original_response_bytes,
|
|
595
|
+
)
|
|
596
|
+
except TypeError as e:
|
|
597
|
+
log.error(
|
|
598
|
+
"%s Failed to serialize original MCP tool response dictionary: %s. Returning original response object.",
|
|
599
|
+
log_identifier,
|
|
600
|
+
e,
|
|
601
|
+
)
|
|
602
|
+
return tool_response
|
|
603
|
+
needs_truncation_for_llm = original_response_bytes > llm_max_bytes
|
|
604
|
+
needs_saving_as_artifact = (
|
|
605
|
+
original_response_bytes > save_threshold
|
|
606
|
+
) or needs_truncation_for_llm
|
|
607
|
+
else:
|
|
608
|
+
needs_truncation_for_llm = False
|
|
609
|
+
needs_saving_as_artifact = True
|
|
648
610
|
|
|
649
|
-
|
|
611
|
+
save_result = None
|
|
650
612
|
if needs_saving_as_artifact:
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
log_identifier,
|
|
654
|
-
original_response_bytes,
|
|
655
|
-
save_threshold,
|
|
656
|
-
llm_max_bytes,
|
|
657
|
-
)
|
|
658
|
-
saved_artifact_details = await _save_mcp_response_as_artifact(
|
|
659
|
-
tool, tool_context, host_component, mcp_response_dict, args
|
|
613
|
+
save_result = await save_mcp_response_as_artifact_intelligent(
|
|
614
|
+
tool, tool_context, host_component, mcp_response_dict, cleaned_args
|
|
660
615
|
)
|
|
661
|
-
if
|
|
662
|
-
saved_artifact_details.get("status") == "success"
|
|
663
|
-
or saved_artifact_details.get("status") == "partial_success"
|
|
664
|
-
):
|
|
616
|
+
if save_result.status == McpSaveStatus.ERROR:
|
|
665
617
|
log.warning(
|
|
666
618
|
"%s Failed to save artifact: %s. Proceeding without saved artifact details.",
|
|
667
619
|
log_identifier,
|
|
668
|
-
|
|
620
|
+
save_result.message,
|
|
669
621
|
)
|
|
670
622
|
|
|
671
623
|
final_llm_response_dict: Dict[str, Any] = {}
|
|
@@ -692,27 +644,36 @@ async def manage_large_mcp_tool_responses_callback(
|
|
|
692
644
|
f"The response from tool '{tool.name}' was too large ({original_response_bytes} bytes) for direct display and has been truncated."
|
|
693
645
|
)
|
|
694
646
|
log.debug("%s MCP tool output truncated for LLM.", log_identifier)
|
|
695
|
-
else:
|
|
696
|
-
final_llm_response_dict["mcp_tool_output"] = mcp_response_dict
|
|
697
|
-
log.debug(
|
|
698
|
-
"%s MCP tool output is the full original response for LLM.", log_identifier
|
|
699
|
-
)
|
|
700
647
|
|
|
701
648
|
if needs_saving_as_artifact:
|
|
702
|
-
if
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
649
|
+
if save_result and save_result.status in [
|
|
650
|
+
McpSaveStatus.SUCCESS,
|
|
651
|
+
McpSaveStatus.PARTIAL_SUCCESS,
|
|
652
|
+
]:
|
|
706
653
|
final_llm_response_dict["saved_mcp_response_artifact_details"] = (
|
|
707
|
-
|
|
708
|
-
)
|
|
709
|
-
filename = saved_artifact_details.get(
|
|
710
|
-
"data_filename", "unknown_artifact.json"
|
|
711
|
-
)
|
|
712
|
-
version = saved_artifact_details.get("data_version", "N/A")
|
|
713
|
-
message_parts_for_llm.append(
|
|
714
|
-
f"The full response has been saved as artifact '{filename}' (version {version})."
|
|
654
|
+
save_result.model_dump(exclude_none=True)
|
|
715
655
|
)
|
|
656
|
+
|
|
657
|
+
total_artifacts = len(save_result.artifacts_saved)
|
|
658
|
+
if total_artifacts > 0:
|
|
659
|
+
first_artifact = save_result.artifacts_saved[0]
|
|
660
|
+
filename = first_artifact.data_filename
|
|
661
|
+
version = first_artifact.data_version
|
|
662
|
+
if total_artifacts > 1:
|
|
663
|
+
message_parts_for_llm.append(
|
|
664
|
+
f"The full response has been saved as {total_artifacts} artifacts, starting with '{filename}' (version {version})."
|
|
665
|
+
)
|
|
666
|
+
else:
|
|
667
|
+
message_parts_for_llm.append(
|
|
668
|
+
f"The full response has been saved as artifact '{filename}' (version {version})."
|
|
669
|
+
)
|
|
670
|
+
elif save_result.fallback_artifact:
|
|
671
|
+
filename = save_result.fallback_artifact.data_filename
|
|
672
|
+
version = save_result.fallback_artifact.data_version
|
|
673
|
+
message_parts_for_llm.append(
|
|
674
|
+
f"The full response has been saved as artifact '{filename}' (version {version})."
|
|
675
|
+
)
|
|
676
|
+
|
|
716
677
|
log.debug(
|
|
717
678
|
"%s Added saved artifact details to LLM response.", log_identifier
|
|
718
679
|
)
|
|
@@ -720,21 +681,21 @@ async def manage_large_mcp_tool_responses_callback(
|
|
|
720
681
|
message_parts_for_llm.append(
|
|
721
682
|
"Saving the full response as an artifact failed."
|
|
722
683
|
)
|
|
723
|
-
|
|
724
|
-
"
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
),
|
|
728
|
-
"filename": saved_artifact_details.get("data_filename", "unknown"),
|
|
729
|
-
}
|
|
684
|
+
if save_result:
|
|
685
|
+
final_llm_response_dict["saved_mcp_response_artifact_details"] = (
|
|
686
|
+
save_result.model_dump(exclude_none=True)
|
|
687
|
+
)
|
|
730
688
|
log.warning(
|
|
731
689
|
"%s Artifact save failed, error details included in LLM response.",
|
|
732
690
|
log_identifier,
|
|
733
691
|
)
|
|
692
|
+
else:
|
|
693
|
+
final_llm_response_dict["mcp_tool_output"] = mcp_response_dict
|
|
734
694
|
|
|
735
695
|
if needs_saving_as_artifact and (
|
|
736
|
-
|
|
737
|
-
|
|
696
|
+
save_result
|
|
697
|
+
and save_result.status
|
|
698
|
+
in [McpSaveStatus.SUCCESS, McpSaveStatus.PARTIAL_SUCCESS]
|
|
738
699
|
):
|
|
739
700
|
if needs_truncation_for_llm:
|
|
740
701
|
final_llm_response_dict["status"] = "processed_saved_and_truncated"
|
|
@@ -785,6 +746,7 @@ It can span multiple lines.
|
|
|
785
746
|
|
|
786
747
|
The system will automatically save the content and give you a confirmation in the next turn."""
|
|
787
748
|
|
|
749
|
+
|
|
788
750
|
def _generate_artifact_creation_instruction() -> str:
|
|
789
751
|
return """
|
|
790
752
|
**Creating Text-Based Artifacts:**
|
|
@@ -806,6 +768,7 @@ def _generate_artifact_creation_instruction() -> str:
|
|
|
806
768
|
- Basic explanations that don't require reference material
|
|
807
769
|
"""
|
|
808
770
|
|
|
771
|
+
|
|
809
772
|
def _generate_embed_instruction(
|
|
810
773
|
include_artifact_content: bool,
|
|
811
774
|
log_identifier: str,
|
|
@@ -1201,6 +1164,7 @@ async def after_tool_callback_inject_metadata(
|
|
|
1201
1164
|
metadata_part.inline_data.data.decode("utf-8")
|
|
1202
1165
|
)
|
|
1203
1166
|
metadata_dict["version"] = version
|
|
1167
|
+
metadata_dict["filename"] = filename
|
|
1204
1168
|
formatted_text = format_metadata_for_llm(metadata_dict)
|
|
1205
1169
|
metadata_texts.append(formatted_text)
|
|
1206
1170
|
log.info(
|