From d7b69bfabcecda3b9e51f49310b67d501396ebfd Mon Sep 17 00:00:00 2001 From: Torantulino <40276179@live.napier.ac.uk> Date: Mon, 26 Jan 2026 20:53:13 +0100 Subject: [PATCH] fix(backend): Add synthetic execution context to run_block for CoPilot Add synthetic execution context parameters (`graph_exec_id`, `node_exec_id`, `graph_id`) to enable 20+ blocks that require file storage, unique output filenames, or memory segmentation to work in CoPilot standalone execution. - Generate `copilot-{session_id}-{uuid}` for file storage isolation - Generate unique `node_exec_id` for media block output filenames - Use `copilot-{user_id}` as graph_id for Mem0 memory segmentation - Add cleanup of temporary files after execution (success or failure) Fixes SECRT-1833 Co-Authored-By: Claude Opus 4.5 --- .../api/features/chat/tools/run_block.py | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/autogpt_platform/backend/backend/api/features/chat/tools/run_block.py b/autogpt_platform/backend/backend/api/features/chat/tools/run_block.py index c29cc92556..15da49262c 100644 --- a/autogpt_platform/backend/backend/api/features/chat/tools/run_block.py +++ b/autogpt_platform/backend/backend/api/features/chat/tools/run_block.py @@ -1,6 +1,7 @@ """Tool for executing blocks directly.""" import logging +import uuid from collections import defaultdict from typing import Any @@ -12,6 +13,7 @@ from backend.data.execution import ExecutionContext from backend.data.model import CredentialsMetaInput from backend.integrations.creds_manager import IntegrationCredentialsManager from backend.util.exceptions import BlockError +from backend.util.file import clean_exec_files from .base import BaseTool from .models import ( @@ -221,10 +223,21 @@ class RunBlockTool(BaseTool): ) try: - # Fetch actual credentials and prepare kwargs for block execution - # Create execution context with defaults (blocks may require it) + # Generate synthetic execution context for standalone block execution + synthetic_exec_id = f"copilot-{session.session_id}-{uuid.uuid4().hex[:8]}" + exec_kwargs: dict[str, Any] = { "user_id": user_id, + # File storage isolation - creates {temp}/exec_file/{graph_exec_id}/ + "graph_exec_id": synthetic_exec_id, + # Unique output filenames (for media blocks like LoopVideoBlock) + "node_exec_id": f"{synthetic_exec_id}-{uuid.uuid4().hex[:8]}", + # Memory segmentation (for Mem0 blocks) - user-scoped + "graph_id": f"copilot-{user_id}", + # Standard context + "graph_version": 1, + "node_id": block_id, + # Execution context with defaults (blocks may require it) "execution_context": ExecutionContext(), } @@ -253,6 +266,9 @@ class RunBlockTool(BaseTool): ): outputs[output_name].append(output_data) + # Clean up temporary files from this execution + clean_exec_files(synthetic_exec_id) + return BlockOutputResponse( message=f"Block '{block.name}' executed successfully", block_id=block_id, @@ -264,6 +280,9 @@ class RunBlockTool(BaseTool): except BlockError as e: logger.warning(f"Block execution failed: {e}") + # Clean up temporary files even on failure + if "synthetic_exec_id" in locals(): + clean_exec_files(synthetic_exec_id) return ErrorResponse( message=f"Block execution failed: {e}", error=str(e), @@ -271,6 +290,9 @@ class RunBlockTool(BaseTool): ) except Exception as e: logger.error(f"Unexpected error executing block: {e}", exc_info=True) + # Clean up temporary files even on failure + if "synthetic_exec_id" in locals(): + clean_exec_files(synthetic_exec_id) return ErrorResponse( message=f"Failed to execute block: {str(e)}", error=str(e),