mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-11 23:35:25 -05:00
fix: Use timestamp-based file extraction instead of /output directory
Replace the hardcoded /output directory approach with timestamp-based file extraction (matching ClaudeCodeBlock's pattern). This removes the need to create a special directory and captures any files created or modified during execution in /home/user. Also fixes a potential UnboundLocalError in sandbox_files.py where data_uri could be referenced in the except block before assignment, and moves base64/mimetypes to top-level imports. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -92,8 +92,8 @@ class CodeExecutionResult(MainCodeExecutionResult):
|
||||
class BaseE2BExecutorMixin:
|
||||
"""Shared implementation methods for E2B executor blocks."""
|
||||
|
||||
# Default output directory for file extraction
|
||||
OUTPUT_DIR = "/output"
|
||||
# Default working directory in E2B sandboxes
|
||||
WORKING_DIR = "/home/user"
|
||||
|
||||
async def execute_code(
|
||||
self,
|
||||
@@ -115,8 +115,8 @@ class BaseE2BExecutorMixin:
|
||||
3. Connect to existing sandbox and execute (ExecuteCodeStepBlock)
|
||||
|
||||
Args:
|
||||
extract_files: If True and execution_context provided, extract files from
|
||||
/output directory and store to workspace.
|
||||
extract_files: If True and execution_context provided, extract files
|
||||
created/modified during execution and store to workspace.
|
||||
""" # noqa
|
||||
sandbox = None
|
||||
files: list[SandboxFileOutput] = []
|
||||
@@ -131,13 +131,16 @@ class BaseE2BExecutorMixin:
|
||||
sandbox = await AsyncSandbox.create(
|
||||
api_key=api_key, template=template_id, timeout=timeout
|
||||
)
|
||||
# Create /output directory for file extraction
|
||||
if extract_files:
|
||||
await sandbox.commands.run(f"mkdir -p {self.OUTPUT_DIR}")
|
||||
if setup_commands:
|
||||
for cmd in setup_commands:
|
||||
await sandbox.commands.run(cmd)
|
||||
|
||||
# Capture timestamp before execution to scope file extraction
|
||||
start_timestamp = None
|
||||
if extract_files:
|
||||
ts_result = await sandbox.commands.run("date -u +%Y-%m-%dT%H:%M:%S")
|
||||
start_timestamp = ts_result.stdout.strip() if ts_result.stdout else None
|
||||
|
||||
# Execute the code
|
||||
execution = await sandbox.run_code(
|
||||
code,
|
||||
@@ -153,13 +156,13 @@ class BaseE2BExecutorMixin:
|
||||
stdout_logs = "".join(execution.logs.stdout)
|
||||
stderr_logs = "".join(execution.logs.stderr)
|
||||
|
||||
# Extract files from /output if requested
|
||||
# Extract files created/modified during this execution
|
||||
if extract_files and execution_context:
|
||||
files = await extract_and_store_sandbox_files(
|
||||
sandbox=sandbox,
|
||||
working_directory=self.OUTPUT_DIR,
|
||||
working_directory=self.WORKING_DIR,
|
||||
execution_context=execution_context,
|
||||
since_timestamp=None, # Get all files in /output
|
||||
since_timestamp=start_timestamp,
|
||||
text_only=False, # Include binary files too
|
||||
)
|
||||
|
||||
@@ -277,7 +280,7 @@ class ExecuteCodeBlock(Block, BaseE2BExecutorMixin):
|
||||
stderr_logs: str = SchemaField(description="Standard error logs from execution")
|
||||
files: list[SandboxFileOutput] = SchemaField(
|
||||
description=(
|
||||
"Files written to /output directory during execution. "
|
||||
"Files created or modified during execution. "
|
||||
"Each file has path, name, content, and workspace_ref (if stored)."
|
||||
),
|
||||
)
|
||||
|
||||
@@ -5,7 +5,9 @@ This module provides common file extraction and workspace storage functionality
|
||||
for blocks that run code in E2B sandboxes (Claude Code, Code Executor, etc.).
|
||||
"""
|
||||
|
||||
import base64
|
||||
import logging
|
||||
import mimetypes
|
||||
import shlex
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING
|
||||
@@ -217,18 +219,13 @@ async def store_sandbox_files(
|
||||
else:
|
||||
content_str = f"[Binary file: {len(file.content)} bytes]"
|
||||
|
||||
# Build data URI (needed for storage and as binary fallback)
|
||||
mime_type = mimetypes.guess_type(file.name)[0] or "application/octet-stream"
|
||||
data_uri = f"data:{mime_type};base64,{base64.b64encode(file.content).decode()}"
|
||||
|
||||
# Try to store in workspace
|
||||
workspace_ref: str | None = None
|
||||
try:
|
||||
# Convert bytes to data URI for store_media_file
|
||||
import base64
|
||||
import mimetypes
|
||||
|
||||
mime_type = mimetypes.guess_type(file.name)[0] or "application/octet-stream"
|
||||
data_uri = (
|
||||
f"data:{mime_type};base64,{base64.b64encode(file.content).decode()}"
|
||||
)
|
||||
|
||||
result = await store_media_file(
|
||||
file=MediaFileType(data_uri),
|
||||
execution_context=execution_context,
|
||||
|
||||
@@ -215,7 +215,7 @@ The sandbox includes pip and npm pre-installed. Set timeout to limit execution t
|
||||
| response | Text output (if any) of the main execution result | str |
|
||||
| stdout_logs | Standard output logs from execution | str |
|
||||
| stderr_logs | Standard error logs from execution | str |
|
||||
| files | Files written to /output directory during execution. Each file has path, name, content, and workspace_ref (if stored). | List[SandboxFileOutput] |
|
||||
| files | Files created or modified during execution. Each file has path, name, content, and workspace_ref (if stored). | List[SandboxFileOutput] |
|
||||
|
||||
### Possible use case
|
||||
<!-- MANUAL: use_case -->
|
||||
|
||||
Reference in New Issue
Block a user