Read a line range plus metadata from a workspace file.
(
path: Annotated[str, ParamMeta(description="Workspace-relative text file path")],
*,
start_line: Annotated[int, ParamMeta(description="1-based line to begin the snippet")]=1,
line_count: Annotated[int, ParamMeta(description="Number of lines to include starting from start_line")]=40,
inline_line_numbers: Annotated[
bool,
ParamMeta(description="If true, prefix each snippet line with its line number inside the snippet"),
] = False,
encoding: Annotated[str, ParamMeta(description="Explicit encoding or 'auto'")]="auto",
include_line_offsets: Annotated[
bool,
ParamMeta(description="Include 1-based line metadata for the returned snippet"),
] = False,
_context: Dict[str, Any] | None = None,
)
| 445 | |
| 446 | |
| 447 | def read_file_segment( |
| 448 | path: Annotated[str, ParamMeta(description="Workspace-relative text file path")], |
| 449 | *, |
| 450 | start_line: Annotated[int, ParamMeta(description="1-based line to begin the snippet")]=1, |
| 451 | line_count: Annotated[int, ParamMeta(description="Number of lines to include starting from start_line")]=40, |
| 452 | inline_line_numbers: Annotated[ |
| 453 | bool, |
| 454 | ParamMeta(description="If true, prefix each snippet line with its line number inside the snippet"), |
| 455 | ] = False, |
| 456 | encoding: Annotated[str, ParamMeta(description="Explicit encoding or 'auto'")]="auto", |
| 457 | include_line_offsets: Annotated[ |
| 458 | bool, |
| 459 | ParamMeta(description="Include 1-based line metadata for the returned snippet"), |
| 460 | ] = False, |
| 461 | _context: Dict[str, Any] | None = None, |
| 462 | ) -> Dict[str, Any]: |
| 463 | """Read a line range plus metadata from a workspace file.""" |
| 464 | |
| 465 | if start_line < 1: |
| 466 | raise ValueError("start_line must be >= 1") |
| 467 | if line_count < 1: |
| 468 | raise ValueError("line_count must be >= 1") |
| 469 | |
| 470 | ctx = FileToolContext(_context) |
| 471 | target = ctx.resolve_under_workspace(path) |
| 472 | if not target.exists() or not target.is_file(): |
| 473 | raise FileNotFoundError(f"File not found: {path}") |
| 474 | |
| 475 | text, used_encoding = _read_text_content(target, encoding) |
| 476 | newline_style = _detect_newline(text) |
| 477 | stat = target.stat() |
| 478 | |
| 479 | lines_with_breaks = text.splitlines(keepends=True) |
| 480 | if not lines_with_breaks: |
| 481 | lines_with_breaks = [""] |
| 482 | total_lines = len(lines_with_breaks) |
| 483 | start_idx = start_line - 1 |
| 484 | if start_idx >= total_lines: |
| 485 | raise ValueError("start_line is beyond the total number of lines in the file") |
| 486 | |
| 487 | lines_returned = min(line_count, total_lines - start_idx) |
| 488 | end_idx = start_idx + lines_returned |
| 489 | segment_lines = lines_with_breaks[start_idx:end_idx] |
| 490 | snippet = "".join(segment_lines) |
| 491 | raw_snippet = snippet |
| 492 | |
| 493 | line_starts: List[int] = [0] |
| 494 | for line in lines_with_breaks: |
| 495 | line_starts.append(line_starts[-1] + len(line)) |
| 496 | start_char = line_starts[start_idx] |
| 497 | |
| 498 | response: Dict[str, Any] = { |
| 499 | "path": ctx.to_workspace_relative(target), |
| 500 | "encoding": used_encoding, |
| 501 | "newline": newline_style, |
| 502 | "start_line": start_line, |
| 503 | "end_line": start_line + lines_returned - 1, |
| 504 | "line_count": line_count, |
nothing calls this directly
no test coverage detected