Skip to content

Commit 92c4163

Browse files
authored
Merge pull request #1840 from trungutt/revert/pr-1828-filesystem-pagination
Revert "builtin: add offset and line_count pagination to read_file and read_multiple_files"
2 parents 6c0f671 + ab82b45 commit 92c4163

File tree

9 files changed

+79
-123
lines changed

9 files changed

+79
-123
lines changed

e2e/testdata/cassettes/TestExec_Anthropic_ToolCall.yaml

Lines changed: 17 additions & 17 deletions
Large diffs are not rendered by default.

e2e/testdata/cassettes/TestExec_Gemini_ToolCall.yaml

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

e2e/testdata/cassettes/TestExec_Mistral_ToolCall.yaml

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

e2e/testdata/cassettes/TestExec_OpenAI_HideToolCalls.yaml

Lines changed: 20 additions & 20 deletions
Large diffs are not rendered by default.

e2e/testdata/cassettes/TestExec_OpenAI_ToolCall.yaml

Lines changed: 20 additions & 20 deletions
Large diffs are not rendered by default.

e2e/testdata/cassettes/TestExec_ToolCallsNeedAcceptance.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interactions:
88
proto_minor: 1
99
content_length: 0
1010
host: api.openai.com
11-
body: '{"input":[{"content":[{"text":"You are a knowledgeable assistant that can write test files.","type":"input_text"}],"role":"system"},{"content":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","type":"input_text"}],"role":"system"},{"content":"Create a hello.txt file with \"Hello, World!\" content. Try only once. On error, exit without further message.","role":"user"}],"model":"gpt-5-mini","tools":[{"strict":true,"parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","type":"function"}],"stream":true}'
11+
body: '{"input":[{"content":[{"text":"You are a knowledgeable assistant that can write test files.","type":"input_text"}],"role":"system"},{"content":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","type":"input_text"}],"role":"system"},{"content":"Create a hello.txt file with \"Hello, World!\" content. Try only once. On error, exit without further message.","role":"user"}],"model":"gpt-5-mini","tools":[{"strict":true,"parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","type":"function"}],"stream":true}'
1212
url: https://api.openai.com/v1/responses
1313
method: POST
1414
response:
@@ -91,7 +91,7 @@ interactions:
9191
proto_minor: 1
9292
content_length: 0
9393
host: api.openai.com
94-
body: '{"input":[{"content":[{"text":"You are a knowledgeable assistant that can write test files.","type":"input_text"}],"role":"system"},{"content":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","type":"input_text"}],"role":"system"},{"content":"Create a hello.txt file with \"Hello, World!\" content. Try only once. On error, exit without further message.","role":"user"},{"arguments":"{\"content\":\"Hello, World!\",\"path\":\"hello.txt\"}","call_id":"call_5W18F6XkDh9NllAH9r0P9GuF","name":"write_file","type":"function_call"},{"call_id":"call_5W18F6XkDh9NllAH9r0P9GuF","output":"The user rejected the tool call.","type":"function_call_output"}],"model":"gpt-5-mini","tools":[{"strict":true,"parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","type":"function"}],"stream":true}'
94+
body: '{"input":[{"content":[{"text":"You are a knowledgeable assistant that can write test files.","type":"input_text"}],"role":"system"},{"content":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","type":"input_text"}],"role":"system"},{"content":"Create a hello.txt file with \"Hello, World!\" content. Try only once. On error, exit without further message.","role":"user"},{"arguments":"{\"content\":\"Hello, World!\",\"path\":\"hello.txt\"}","call_id":"call_5W18F6XkDh9NllAH9r0P9GuF","name":"write_file","type":"function_call"},{"call_id":"call_5W18F6XkDh9NllAH9r0P9GuF","output":"The user rejected the tool call.","type":"function_call_output"}],"model":"gpt-5-mini","tools":[{"strict":true,"parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","type":"function"}],"stream":true}'
9595
url: https://api.openai.com/v1/responses
9696
method: POST
9797
response:

pkg/tools/builtin/filesystem.go

Lines changed: 14 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,7 @@ This toolset provides comprehensive filesystem operations.
9191
### Performance Tips
9292
- Use read_multiple_files instead of multiple read_file calls
9393
- Use directory_tree with max_depth to limit large traversals
94-
- Use appropriate exclude patterns in search operations
95-
96-
### Reading Large Files
97-
- read_file and read_multiple_files support offset and line_count parameters for pagination
98-
- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count
99-
- The response includes total_lines so you know how many more lines remain
100-
- Continue reading with an incremented offset until you have read all required content`
94+
- Use appropriate exclude patterns in search operations`
10195
}
10296

10397
type DirectoryTreeArgs struct {
@@ -110,10 +104,8 @@ type WriteFileArgs struct {
110104
}
111105

112106
type ReadMultipleFilesArgs struct {
113-
Paths []string `json:"paths" jsonschema:"Array of file paths to read"`
114-
JSON bool `json:"json,omitempty" jsonschema:"Whether to return the result as JSON"`
115-
Offset int `json:"offset,omitempty" jsonschema:"1-based line number to start reading from, applied to all files (default: 1)"`
116-
LineCount int `json:"line_count,omitempty" jsonschema:"Maximum number of lines to return per file (default: all remaining lines)"`
107+
Paths []string `json:"paths" jsonschema:"Array of file paths to read"`
108+
JSON bool `json:"json,omitempty" jsonschema:"Whether to return the result as JSON"`
117109
}
118110

119111
type ReadMultipleFilesMeta struct {
@@ -149,16 +141,14 @@ type DirectoryTreeMeta struct {
149141
}
150142

151143
type ReadFileArgs struct {
152-
Path string `json:"path" jsonschema:"The file path to read"`
153-
Offset int `json:"offset,omitempty" jsonschema:"1-based line number to start reading from (default: 1)"`
154-
LineCount int `json:"line_count,omitempty" jsonschema:"Maximum number of lines to return (default: all remaining lines)"`
144+
Path string `json:"path" jsonschema:"The file path to read"`
155145
}
156146

157147
type ReadFileMeta struct {
158-
Path string `json:"path"`
159-
Content string `json:"content"`
160-
TotalLines int `json:"totalLines"`
161-
Error string `json:"error,omitempty"`
148+
Path string `json:"path"`
149+
Content string `json:"content"`
150+
LineCount int `json:"lineCount"`
151+
Error string `json:"error,omitempty"`
162152
}
163153

164154
type Edit struct {
@@ -236,7 +226,7 @@ func (t *FilesystemTool) Tools(context.Context) ([]tools.Tool, error) {
236226
{
237227
Name: ToolNameReadFile,
238228
Category: "filesystem",
239-
Description: "Read the contents of a file from the file system.",
229+
Description: "Read the complete contents of a file from the file system.",
240230
Parameters: tools.MustSchemaFor[ReadFileArgs](),
241231
OutputSchema: tools.MustSchemaFor[string](),
242232
Handler: tools.NewHandler(t.handleReadFile),
@@ -493,38 +483,6 @@ func (t *FilesystemTool) handleListDirectory(_ context.Context, args ListDirecto
493483
}, nil
494484
}
495485

496-
// applyLineWindow slices lines from a file's content according to offset (1-based) and
497-
// lineCount (0 means all remaining lines). It returns the windowed content and the total
498-
// line count of the original. A header is prepended when only a subset is returned.
499-
func applyLineWindow(content, path string, offset, lineCount int) (windowed string, totalLines int) {
500-
lines := strings.Split(content, "\n")
501-
totalLines = len(lines)
502-
503-
// Normalise offset: default to 1, clamp to valid range
504-
if offset <= 0 {
505-
offset = 1
506-
}
507-
if offset > totalLines {
508-
offset = totalLines
509-
}
510-
511-
// Convert to 0-based index
512-
from := offset - 1
513-
to := totalLines
514-
if lineCount > 0 && from+lineCount < totalLines {
515-
to = from + lineCount
516-
}
517-
518-
windowed = strings.Join(lines[from:to], "\n")
519-
520-
// Prepend a header only when we are returning a subset of the file
521-
if from > 0 || to < totalLines {
522-
windowed = fmt.Sprintf("[Showing lines %d-%d of %d from %s]\n%s", offset, to, totalLines, path, windowed)
523-
}
524-
525-
return windowed, totalLines
526-
}
527-
528486
func (t *FilesystemTool) handleReadFile(_ context.Context, args ReadFileArgs) (*tools.ToolCallResult, error) {
529487
resolvedPath := t.resolvePath(args.Path)
530488

@@ -546,11 +504,10 @@ func (t *FilesystemTool) handleReadFile(_ context.Context, args ReadFileArgs) (*
546504
}, nil
547505
}
548506

549-
windowed, totalLines := applyLineWindow(string(content), args.Path, args.Offset, args.LineCount)
550507
return &tools.ToolCallResult{
551-
Output: windowed,
508+
Output: string(content),
552509
Meta: ReadFileMeta{
553-
TotalLines: totalLines,
510+
LineCount: strings.Count(string(content), "\n") + 1,
554511
},
555512
}, nil
556513
}
@@ -588,13 +545,12 @@ func (t *FilesystemTool) handleReadMultipleFiles(ctx context.Context, args ReadM
588545
continue
589546
}
590547

591-
windowed, totalLines := applyLineWindow(string(content), path, args.Offset, args.LineCount)
592548
contents = append(contents, PathContent{
593549
Path: path,
594-
Content: windowed,
550+
Content: string(content),
595551
})
596-
entry.Content = windowed
597-
entry.TotalLines = totalLines
552+
entry.Content = string(content)
553+
entry.LineCount = strings.Count(string(content), "\n") + 1
598554
meta.Files = append(meta.Files, entry)
599555
}
600556

pkg/tui/components/tool/readfile/readfile.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ func extractResult(msg *types.Message) string {
2828
if meta.Error != "" {
2929
return meta.Error
3030
}
31-
return fmt.Sprintf("%d lines", meta.TotalLines)
31+
return fmt.Sprintf("%d lines", meta.LineCount)
3232
}

pkg/tui/components/tool/readmultiplefiles/readmultiplefiles.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func formatSummaryLines(meta *builtin.ReadMultipleFilesMeta) []fileSummary {
9999
if file.Error != "" {
100100
output = " " + file.Error
101101
} else {
102-
output = fmt.Sprintf(" %d lines", file.TotalLines)
102+
output = fmt.Sprintf(" %d lines", file.LineCount)
103103
}
104104

105105
summaries = append(summaries, fileSummary{

0 commit comments

Comments
 (0)