fix(agent): preserve sandbox file errors in stdout 🤖🤖🤖 (#42624)

This commit is contained in:
zyssyz123 authored and GitHub committed 2026-09-21 04:34:28 +00:00
1 parent 3e787d11cc
commit d2c2e39ba7
2 files changed
+30 -3

No files matched your search

@@ -50,6 +50,10 @@ import os
import stat
import sys
# The shell transport may expose stdout only. Keep Python errors in the same
# stream so the server can classify unavailable paths instead of returning 502.
sys.stderr = sys.stdout
path = sys.argv[1]
response_path = sys.argv[2]
limit = int(sys.argv[3])
@@ -89,6 +93,8 @@ import os
import stat
import sys
sys.stderr = sys.stdout
path = sys.argv[1]
response_path = sys.argv[2]
max_bytes = int(sys.argv[3])
@@ -117,6 +117,8 @@ class _ProviderErrorCommands(_Commands):
@dataclass(slots=True)
class _LocalCommands(_Commands):
capture_stderr: bool = True
async def run(
self,
script: str,
@@ -133,7 +135,7 @@ class _LocalCommands(_Commands):
cwd=cwd,
env={**os.environ, **(env or {})},
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.STDOUT,
stderr=asyncio.subprocess.STDOUT if self.capture_stderr else asyncio.subprocess.DEVNULL,
)
output, _ = await asyncio.wait_for(process.communicate(), timeout=timeout)
text = output.decode(errors="replace")
@@ -195,12 +197,16 @@ def _service(
return service, backend
def _local_service(tmp_path: Path) -> tuple[BindingFileService, _Backend, _LocalCommands, Path, Path]:
def _local_service(
tmp_path: Path,
*,
capture_stderr: bool = True,
) -> tuple[BindingFileService, _Backend, _LocalCommands, Path, Path]:
workspace = tmp_path / "workspace"
home = tmp_path / "home"
workspace.mkdir()
home.mkdir()
commands = _LocalCommands(outputs=[])
commands = _LocalCommands(outputs=[], capture_stderr=capture_stderr)
backend = _Backend(
lease=cast(
RuntimeLease,
@@ -412,6 +418,21 @@ async def test_browse_preserves_binding_file_error_and_releases_lease(operation:
assert backend.releases == 1
@pytest.mark.parametrize("operation", ["list", "read"])
@pytest.mark.anyio
async def test_missing_path_is_classified_when_transport_only_captures_stdout(tmp_path: Path, operation: str) -> None:
service, backend, commands, _, _ = _local_service(tmp_path, capture_stderr=False)
with pytest.raises(BindingFileError) as error:
if operation == "list":
await service.list_files(BindingFileListRequest(backend_binding_ref="binding-ref", path="missing"))
else:
await service.read_file(BindingFileReadRequest(backend_binding_ref="binding-ref", path="missing"))
assert error.value.code == "invalid_binding_path"
assert error.value.status_code == 400
assert backend.releases == 1
assert commands.deletes == ["local-job-1"]
@pytest.mark.parametrize("operation", ["list", "read"])
@pytest.mark.anyio
async def test_browse_maps_malformed_backend_response_to_unavailable_and_releases_lease(operation: str) -> None: