From cff7acf683eab6c57690f1871b30870a0fcdc2c0 Mon Sep 17 00:00:00 2001 From: isaacbmiller Date: Mon, 13 Jul 2026 14:06:21 -0400 Subject: [PATCH] fix(interpreter): acknowledge file synchronization --- dspy/primitives/python_interpreter.py | 8 +++++--- dspy/primitives/runner.js | 13 ++++++++----- tests/primitives/test_python_interpreter.py | 12 ++++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/dspy/primitives/python_interpreter.py b/dspy/primitives/python_interpreter.py index 7a45bb5ec9..4596d2e710 100644 --- a/dspy/primitives/python_interpreter.py +++ b/dspy/primitives/python_interpreter.py @@ -266,9 +266,11 @@ def _sync_files(self): for path in self.enable_write_paths: virtual_path = f"/sandbox/{os.path.basename(str(path))}" host_path = _canonicalize_path(path) - sync_msg = _jsonrpc_notification("sync_file", {"virtual_path": virtual_path, "host_path": host_path}) - self.deno_process.stdin.write(sync_msg + "\n") - self.deno_process.stdin.flush() + self._send_request( + "sync_file", + {"virtual_path": virtual_path, "host_path": host_path}, + f"syncing {path}", + ) def _extract_parameters(self, fn: Callable) -> list[dict]: """Extract parameter info from a callable for sandbox registration.""" diff --git a/dspy/primitives/runner.js b/dspy/primitives/runner.js index 170c0f956c..07a3f9a6ce 100644 --- a/dspy/primitives/runner.js +++ b/dspy/primitives/runner.js @@ -244,17 +244,20 @@ while (true) { const requestId = input.id; // May be undefined for notifications // Handle notifications (no response expected) + if (method === "shutdown") break; + if (method === "sync_file") { + const virtualPath = params.virtual_path; + const hostPath = params.host_path || virtualPath; try { - const virtualPath = params.virtual_path; - const hostPath = params.host_path || virtualPath; await Deno.writeFile(hostPath, pyodide.FS.readFile(virtualPath)); - } catch (e) { /* ignore sync errors */ } + console.log(jsonrpcResult({ synced: virtualPath }, requestId)); + } catch (e) { + console.log(jsonrpcError(JSONRPC_APP_ERRORS.RuntimeError, `Failed to sync file: ${e.message}`, requestId)); + } continue; } - if (method === "shutdown") break; - // Handle requests (expect response) if (method === "mount_file") { const hostPath = params.host_path; diff --git a/tests/primitives/test_python_interpreter.py b/tests/primitives/test_python_interpreter.py index 5804e39f88..334fe894b2 100644 --- a/tests/primitives/test_python_interpreter.py +++ b/tests/primitives/test_python_interpreter.py @@ -181,6 +181,18 @@ def test_enable_write_flag(tmp_path): assert f.read() == "original_content", "File should not be changed when sync_files is False" +def test_sync_failure_is_reported(tmp_path): + testfile_path = tmp_path / "sync_failure.txt" + testfile_path.write_text("original_content") + virtual_path = f"/sandbox/{testfile_path.name}" + + with PythonInterpreter(enable_write_paths=[testfile_path]) as interpreter: + with pytest.raises(CodeInterpreterError, match="Failed to sync file"): + interpreter.execute(f"import os\nos.remove({virtual_path!r})") + + assert testfile_path.read_text() == "original_content" + + def test_enable_net_flag(): test_url = "https://example.com"