fix(agent): make preview and browser output parsers linear (#7003)

Six regexes over tool output backtracked polynomially on long whitespace
runs or repeated openers: the browser snapshot generic-line filter and
post-interaction split, the task-row and skill-bullet parsers, the email
"no results" check, and the Google /sorry/ interstitial check.

Rewrite each without overlapping quantifiers, keeping the same matches for
the text these tools emit. Move the /sorry/ check into
is_google_sorry_url() so it can be tested.
This commit is contained in:
nopoz
2026-10-30 22:46:19 -07:00
committed by GitHub
parent a8e0ff1c8e
commit bebf53be3c
3 changed files with 158 additions and 10 deletions
+3 -2
View File
@@ -25,7 +25,7 @@ def compact_browser_observation(value, budget=8000):
# Snapshot text already contains labels and refs in DOM order.
# The refs mapping repeats them and buries menus in raw JSON.
lines = [line for line in snapshot.splitlines()
if not re.fullmatch(r'\s*-?\s*generic(?:\s+\[ref=e\d+\])?:?\s*', line)]
if not re.fullmatch(r'\s*(?:-\s*)?generic(?:\s+\[ref=e\d+\])?:?\s*', line)]
pages.append(('URL: ' + str(url) + '\n' if url else '') + '\n'.join(lines))
elif url:
notices.append('URL: ' + str(url))
@@ -37,7 +37,8 @@ def compact_browser_observation(value, budget=8000):
parsed = json.loads(item)
except (ValueError, TypeError):
# CLI status text precedes the JSON post-interaction state.
parts = re.split(r'\n\n\[(?:post-[^\]]+|page state after failed [^\]]+)\]\n', item)
# Labels are one line; stopping at \n keeps the split linear.
parts = re.split(r'\n\n\[(?:post-[^\]\n]+|page state after failed [^\]\n]+)\]\n', item)
if len(parts) > 1:
for part in parts:
visit(part)