From 33855f1b30f470ee2ba9bd8c28196296d3a667bb Mon Sep 17 00:00:00 2001 From: kshitij <82637225+kshitijk4poor@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:54:08 +0530 Subject: [PATCH] perf(tools): linear-time masking rebuild + last-opener early exit Efficiency review (measured with timeit probes) found two unbounded costs on adversarial inputs: - The masked-range rebuild copied the whole string once per range (O(n*k)): 50k tiny heredocs took 1.7s. Replaced with a single-pass segment join over the (sorted, non-overlapping) ranges: 152ms, and newlines are now counted on the original command instead of re-slicing. - After the last '<<' occurrence no opener can start, but the scanner still walked the remaining text per-char: one heredoc followed by a 1MB tail cost ~150ms. An rfind bound breaks out of the unit loop once the scan passes it: 0.3ms. Typical commands are unaffected (the '<<' fast path already returns first). 30/30 guard tests pass; mutation check re-run on the final stack (no-op mutation -> 11 tests fail, restore -> green). --- tools/shell_heredoc.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tools/shell_heredoc.py b/tools/shell_heredoc.py index 53568783cf..eef9a8322e 100644 --- a/tools/shell_heredoc.py +++ b/tools/shell_heredoc.py @@ -296,8 +296,13 @@ def strip_inert_heredoc_bodies(command: str) -> str: # machine entirely. This function runs on every terminal tool call. if "<<" not in command: return command + # No heredoc opener can start after the last '<<' occurrence; once the + # scan passes it, the rest of the command needs no per-char walk. + last_opener_index = command.rfind("<<") while command_start < len(command): + if command_start > last_opener_index: + break command_end, specs, unknown_operator, has_list_operator = ( _scan_heredoc_command_unit(command, command_start) ) @@ -339,8 +344,16 @@ def strip_inert_heredoc_bodies(command: str) -> str: ranges.extend(body_ranges) command_start = body_cursor - result = command - for start, end in reversed(ranges): - replacement = "\n" * result[start:end].count("\n") - result = result[:start] + replacement + result[end:] - return result + if not ranges: + return command + # Single-pass rebuild: ranges are sorted and non-overlapping, so join the + # kept segments with newline-preserving replacements (avoids a quadratic + # full-string copy per masked range on heredoc-heavy commands). + parts: list[str] = [] + previous = 0 + for start, end in ranges: + parts.append(command[previous:start]) + parts.append("\n" * command.count("\n", start, end)) + previous = end + parts.append(command[previous:]) + return "".join(parts)