fix(execute_code): report in-script tool errors the script ignored
A script that calls hermes_tools.write_file/patch and never prints the
returned {"error": ...} got status=success with empty output, so the
model believed the write happened. In a cross-agent bench this cost 3 of
18 Opus runs 4-6 extra turns (write_file refused by the read-before-write
guard, then re-probing and re-emitting whole files). The result now
carries tool_errors for that cell, and the in-script write_file doc says
existing files must be read first.
This commit is contained in:
@@ -314,6 +314,7 @@ class SessionKernel:
|
||||
self.stop_event = threading.Event()
|
||||
self.death_pipe_w: Optional[int] = None
|
||||
self.tool_call_log: List = []
|
||||
self.cell_log_start = 0
|
||||
self.tool_call_counter: List[int] = [0]
|
||||
# Cells currently attached (bumped under the registry lock on selection, dropped when the
|
||||
# cell settles). Reaping/cap-eviction skip attached kernels: tearing one down mid-spawn
|
||||
@@ -802,6 +803,10 @@ def _cell_result(kernel: SessionKernel, key: Tuple, status: str, payload: Dict[s
|
||||
"execution_count": kernel.execution_count, "state_reset": state_reset},
|
||||
}
|
||||
result.update(stdout_metadata)
|
||||
from tools.code_execution_rpc import tool_errors_since
|
||||
tool_errors = tool_errors_since(kernel.tool_call_log, kernel.cell_log_start)
|
||||
if tool_errors:
|
||||
result["tool_errors"] = tool_errors
|
||||
# Cell-side spill (runner clipped before replying): same read_file recipe as the host-side spill.
|
||||
cell_spill = str(payload.get("stdout_spill_path", "") or "")
|
||||
if cell_spill and payload.get("stdout_clipped"):
|
||||
@@ -882,6 +887,7 @@ def _run_cell(kernel: SessionKernel, key: Tuple, code: str, *, task_id: str, chi
|
||||
assert kernel.proc is not None and kernel.proc.stdin is not None
|
||||
# Per-cell tool budget: the RPC loop enforces counter < max; reset without restarting.
|
||||
kernel.tool_call_counter[0] = 0
|
||||
kernel.cell_log_start = len(kernel.tool_call_log)
|
||||
kernel.raw.drain(), kernel.stderr.drain() # raw output leaked between cells belongs to no cell
|
||||
kernel.cell_authority = authority
|
||||
kernel.proc.stdin.write((json.dumps({"id": uuid.uuid4().hex, "code": code}) + "\n").encode("utf-8"))
|
||||
|
||||
Reference in New Issue
Block a user