fix(agent): resolve execute_code cwd from per-session override (#56047)

execute_code's _resolve_child_cwd() only checked the process-global
TERMINAL_CWD env var and os.getcwd(), ignoring the per-session cwd
override registered via session.cwd.set → register_task_env_overrides.

This caused execute_code to write to the process launch directory
while sibling tools (write_file, read_file, patch, terminal) correctly
resolved the session workspace — two file-writing paths in one turn
silently disagreed on the working directory.

Fix: pass task_id to _resolve_child_cwd() and check
_registered_task_cwd_override(task_id) before falling back to
TERMINAL_CWD and os.getcwd(), matching the lookup order used by
file_tools._resolve_base_dir and terminal_tool._resolve_command_cwd.
This commit is contained in:
AlexFucuson9 2026-07-01 11:28:09 +07:00 committed by Teknium
parent 2fd36b17c5
commit 298a94926f

View file

@ -1339,7 +1339,7 @@ def execute_code(
# Env scrubbing and tool whitelist apply identically in both modes.
_mode = _get_execution_mode()
_child_python = _resolve_child_python(_mode)
_child_cwd = _resolve_child_cwd(_mode, tmpdir)
_child_cwd = _resolve_child_cwd(_mode, tmpdir, task_id=task_id)
_script_path = os.path.join(tmpdir, "script.py")
proc = subprocess.Popen(
@ -1745,17 +1745,29 @@ def _resolve_child_python(mode: str) -> str:
return sys.executable
def _resolve_child_cwd(mode: str, staging_dir: str) -> str:
def _resolve_child_cwd(mode: str, staging_dir: str, task_id: Optional[str] = None) -> str:
"""Resolve the working directory for the execute_code subprocess.
- ``strict``: the staging tmpdir (today's behavior).
- ``project``: the session's TERMINAL_CWD (same as the terminal tool), or
``os.getcwd()`` if TERMINAL_CWD is unset or doesn't point at a real dir.
- ``project``: the session's registered cwd override (from
``session.cwd.set``), then ``TERMINAL_CWD``, then ``os.getcwd()``.
Falls back to the staging tmpdir as a last resort so we never invoke
Popen with a nonexistent cwd.
"""
if mode != "project":
return staging_dir
# Check per-session cwd override first (registered via session.cwd.set
# → register_task_env_overrides). This is the same lookup used by
# write_file/read_file/patch/terminal so all tool paths agree on the
# working directory within a session. (#56047)
if task_id:
try:
from tools.file_tools import _registered_task_cwd_override
override = _registered_task_cwd_override(task_id)
if override and os.path.isdir(override):
return override
except Exception:
pass
raw = os.environ.get("TERMINAL_CWD", "").strip()
if raw:
expanded = os.path.expanduser(raw)