class FSRead
Existing features (ref: opencode read tool):
- Default line limit — cap reads at 2000 lines when no start_line/end_line given, instead of reading the entire file.
- Byte cap — stop reading when cumulative output exceeds 50 KB (MAX_BYTES). Whichever limit (lines or bytes) is hit first wins.
- Per-line truncation — truncate individual lines longer than 2000 chars with a suffix like "... (line truncated to 2000 chars)".
- Pagination hint — when output is truncated, append a hint: "(Showing lines 1-N of M. Use start_line=N+1 to continue.)" When reading completes, append "(End of file - total N lines)".
- Binary file detection — read first 4 KB sample, check for null bytes and known binary extensions (.zip, .exe, .so, .pyc, etc.). Reject with "Cannot read binary file: (path)".
- Directory listing — when file_path points to a directory, list entries (paginated, respecting limit) instead of raising an error.
- File-not-found suggestions — on miss, scan the parent directory for similar names and suggest "Did you mean...?" candidates.
- Return a plain string instead of a Hash — avoids the .to_s repr bloat when ToolCall coerces the result for the LLM message.