diff --git a/evaluation/benchmarks/swe_bench/run_infer.py b/evaluation/benchmarks/swe_bench/run_infer.py index 694d9b7ed3..515864a46e 100644 --- a/evaluation/benchmarks/swe_bench/run_infer.py +++ b/evaluation/benchmarks/swe_bench/run_infer.py @@ -96,7 +96,7 @@ Phase 1. READING: read the problem and reword it in clearer terms Phase 2. RUNNING: install and run the tests on the repository 2.1 Follow the readme 2.2 Install the environment and anything needed - 2.2 Iterate and figure out how to run the tests + 2.2 Iterate and figure out how to run the tests Phase 3. EXPLORATION: find the files that are related to the problem and possible solutions 3.1 Use `grep` to search for relevant methods, classes, keywords and error messages. @@ -238,7 +238,7 @@ def get_config( def initialize_runtime( runtime: Runtime, instance: pd.Series, # this argument is not required - metadata: EvalMetadata + metadata: EvalMetadata, ): """Initialize the runtime for the agent. diff --git a/openhands/runtime/action_execution_server.py b/openhands/runtime/action_execution_server.py index 53ebf28857..c71bf00db1 100644 --- a/openhands/runtime/action_execution_server.py +++ b/openhands/runtime/action_execution_server.py @@ -18,6 +18,7 @@ from contextlib import asynccontextmanager from pathlib import Path from zipfile import ZipFile +from binaryornot.check import is_binary from fastapi import Depends, FastAPI, HTTPException, Request, UploadFile from fastapi.exceptions import RequestValidationError from fastapi.responses import FileResponse, HTMLResponse, JSONResponse @@ -355,6 +356,11 @@ class ActionExecutor: async def read(self, action: FileReadAction) -> Observation: assert self.bash_session is not None + + # Cannot read binary files + if is_binary(action.path): + return ErrorObservation('ERROR_BINARY_FILE') + if action.impl_source == FileReadSource.OH_ACI: result_str, _ = _execute_file_editor( self.file_editor, diff --git a/openhands/runtime/impl/action_execution/action_execution_client.py b/openhands/runtime/impl/action_execution/action_execution_client.py index 3479fc6b4b..e4694ee83e 100644 --- a/openhands/runtime/impl/action_execution/action_execution_client.py +++ b/openhands/runtime/impl/action_execution/action_execution_client.py @@ -39,13 +39,14 @@ from openhands.events.observation import ( from openhands.events.serialization import event_to_dict, observation_from_dict from openhands.events.serialization.action import ACTION_TYPE_TO_CLASS from openhands.integrations.provider import PROVIDER_TOKEN_TYPE -from openhands.mcp import call_tool_mcp as call_tool_mcp_handler, create_mcp_clients, MCPClient +from openhands.mcp import MCPClient, create_mcp_clients +from openhands.mcp import call_tool_mcp as call_tool_mcp_handler from openhands.runtime.base import Runtime from openhands.runtime.plugins import PluginRequirement from openhands.runtime.utils.request import send_request +from openhands.utils.async_utils import call_async_from_sync from openhands.utils.http_session import HttpSession from openhands.utils.tenacity_stop import stop_if_should_exit -from openhands.utils.async_utils import call_async_from_sync def _is_retryable_error(exception): @@ -325,10 +326,11 @@ class ActionExecutionClient(Runtime): async def call_tool_mcp(self, action: McpAction) -> Observation: if self.mcp_clients is None: - self.log('debug', f'Creating MCP clients with servers: {self.config.mcp.sse.mcp_servers}') - self.mcp_clients = await create_mcp_clients( - self.config.mcp.sse.mcp_servers + self.log( + 'debug', + f'Creating MCP clients with servers: {self.config.mcp.sse.mcp_servers}', ) + self.mcp_clients = await create_mcp_clients(self.config.mcp.sse.mcp_servers) return await call_tool_mcp_handler(self.mcp_clients, action) async def aclose(self) -> None: diff --git a/openhands/server/routes/files.py b/openhands/server/routes/files.py index 8bc3ca4749..0372b7f694 100644 --- a/openhands/server/routes/files.py +++ b/openhands/server/routes/files.py @@ -135,6 +135,13 @@ async def select_file(file: str, request: Request): return {'code': content} elif isinstance(observation, ErrorObservation): logger.error(f'Error opening file {file}: {observation}') + + if 'ERROR_BINARY_FILE' in observation.message: + return JSONResponse( + status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE, + content={'error': f'Unable to open binary file: {file}'}, + ) + return JSONResponse( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={'error': f'Error opening file: {observation}'},