diff options
| author | Adam Malczewski <[email protected]> | 2026-03-31 23:10:45 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-03-31 23:10:45 +0900 |
| commit | 57c56daf5906442dacc15951c9b3405f89309839 (patch) | |
| tree | e76890119c0e47acb48f8585222b7a2f5e22df56 /lib/dispatch/tool/files/read_file.rb | |
| parent | 25488d32336e05b69a41391cc7b5153478d3cc8a (diff) | |
| download | dispatch-tool-files-dev.tar.gz dispatch-tool-files-dev.zip | |
impdev
Diffstat (limited to 'lib/dispatch/tool/files/read_file.rb')
| -rw-r--r-- | lib/dispatch/tool/files/read_file.rb | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/dispatch/tool/files/read_file.rb b/lib/dispatch/tool/files/read_file.rb new file mode 100644 index 0000000..c0c5edc --- /dev/null +++ b/lib/dispatch/tool/files/read_file.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +module Dispatch + module Tool + module Files + READ_FILE = Dispatch::Tools::Definition.new( + name: "read_file", + description: "Read the contents of a file. Returns file contents with line numbers.", + parameters: { + type: "object", + properties: { + path: { + type: "string", + description: "Path to the file to read, relative to the worktree root." + }, + start_line: { + type: "integer", + description: "The line number to start reading from (0-based). Defaults to 0." + }, + end_line: { + type: "integer", + description: "The inclusive line number to stop reading at (0-based). Use -1 for end of file." + } + }, + required: %w[path], + additionalProperties: false + } + ) do |params, context| + worktree_path = context[:worktree_path] + path = params[:path] + + resolved = begin + Sandbox.resolve_path(path, worktree_path:) + rescue SandboxError => e + next Dispatch::Tools::Result.failure(error: e.message) + end + + unless File.exist?(resolved) + next Dispatch::Tools::Result.failure(error: "File not found: #{path}") + end + + # Binary file detection: check first 8192 bytes for null bytes + sample = File.binread(resolved, 8192) + if sample.include?("\x00") + next Dispatch::Tools::Result.failure(error: "Cannot read binary file: #{path}") + end + + lines = File.readlines(resolved) + + start_line = params.fetch(:start_line, 0) + end_line = params.fetch(:end_line, -1) + end_line = lines.length - 1 if end_line == -1 + + selected = lines[start_line..end_line] || [] + + # Calculate padding width based on the highest line number + width = end_line.to_s.length + + output = selected.each_with_index.map do |line, idx| + line_num = start_line + idx + "#{line_num.to_s.rjust(width)}: #{line}" + end.join + + Dispatch::Tools::Result.success(output:) + end + end + end +end |
