Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ The format is based on Keep a Changelog, and this project currently tracks chang
- Fixed duplicate response in React TUI caused by double Enter key submission in the input handler.
- Fixed concurrent permission modals overwriting each other in TUI default mode when the LLM returns multiple tool calls in one response; `_ask_permission` now serialises callers via an `asyncio.Lock` so each modal is shown and resolved before the next one is emitted.
- Fixed React TUI Markdown tables to size columns from rendered cell text so inline formatting like code spans and bold text no longer breaks alignment.
- Fixed grep tool crashing with `ValueError` / `LimitOverrunError` when ripgrep outputs a line longer than 64 KB (e.g. minified assets or lock files). The asyncio subprocess stream limit is now 8 MB and oversized lines are skipped rather than terminating the session.

### Changed

Expand Down
14 changes: 12 additions & 2 deletions src/openharness/tools/grep_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ async def _rg_grep(
cwd=str(root),
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
limit=8 * 1024 * 1024, # 8 MB per line — avoids LimitOverrunError on long lines
)
Comment on lines 183 to 187
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 8 MB stream limit value is duplicated here and in _rg_grep_file. Consider extracting it into a module-level constant (e.g., _RG_STREAM_LIMIT_BYTES) so it’s easy to tune and avoids the two call sites drifting over time.

Copilot uses AI. Check for mistakes.

matches: list[str] = []
Expand Down Expand Up @@ -239,6 +240,7 @@ async def _rg_grep_file(
cwd=str(path.parent),
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
limit=8 * 1024 * 1024, # 8 MB per line — avoids LimitOverrunError on long lines
)
Comment on lines 240 to 244
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same duplicated 8 MB stream limit as in _rg_grep. Please consider using a shared constant so future adjustments don’t accidentally update only one of the two subprocess call sites.

Copilot uses AI. Check for mistakes.

matches: list[str] = []
Expand Down Expand Up @@ -282,7 +284,11 @@ async def _collect_rg_matches(
) -> None:
assert process.stdout is not None
while len(matches) < limit:
raw = await process.stdout.readline()
try:
raw = await process.stdout.readline()
except ValueError:
# Line exceeded the stream buffer limit; skip it and continue.
continue
Comment on lines +287 to +291
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behavior: when StreamReader.readline() raises ValueError for an over-limit line, the code skips it and continues. Please add a unit test that simulates process.stdout.readline() raising ValueError once (then returning a normal match / EOF) to prevent regressions and ensure the loop doesn’t terminate or hang.

Copilot uses AI. Check for mistakes.
if not raw:
break
line = raw.decode("utf-8", errors="replace").rstrip("\n")
Expand All @@ -300,7 +306,11 @@ async def _collect_rg_file_matches(
) -> None:
assert process.stdout is not None
while len(matches) < limit:
raw = await process.stdout.readline()
try:
raw = await process.stdout.readline()
except ValueError:
# Line exceeded the stream buffer limit; skip it and continue.
continue
Comment on lines +309 to +313
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add test coverage for this ValueError skip-path in _collect_rg_file_matches as well (simulate readline() raising ValueError and verify the tool continues collecting subsequent lines). This will help ensure long-line output can’t crash the session again.

Copilot uses AI. Check for mistakes.
if not raw:
break
line = raw.decode("utf-8", errors="replace").rstrip("\n")
Expand Down
Loading