feat(tool): read_file tool by lines
This commit is contained in:
parent
13fbc786d6
commit
48a30a4804
3 changed files with 18 additions and 9 deletions
|
|
@ -319,12 +319,12 @@ Text-oriented behavior, optimized for source files, markdown, logs, and configs.
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
* `path` (required): File path
|
* `path` (required): File path
|
||||||
* `start_line` (optional): Starting line number, 1-indexed and inclusive, default `0`
|
* `start_line` (optional): Starting line number, 1-indexed and inclusive, default `1`
|
||||||
* `max_lines` (optional): Maximum number of lines to read, default = all remaining lines until EOF or byte budget
|
* `max_lines` (optional): Maximum number of lines to read, default = all remaining lines until EOF or byte budget
|
||||||
|
|
||||||
Behavior notes:
|
Behavior notes:
|
||||||
|
|
||||||
* Binary-looking files are rejected with guidance to use `read_file`
|
* Binary-looking files are rejected with guidance to switch `read_file` to `mode = bytes`
|
||||||
* Extremely long single lines are truncated rather than skipped
|
* Extremely long single lines are truncated rather than skipped
|
||||||
|
|
||||||
Use `mode = lines` when:
|
Use `mode = lines` when:
|
||||||
|
|
|
||||||
|
|
@ -572,7 +572,7 @@ func (t *ReadFileLinesTool) Execute(ctx context.Context, args map[string]any) *T
|
||||||
}
|
}
|
||||||
sample = sample[:sampleN]
|
sample = sample[:sampleN]
|
||||||
if isBinaryReadFileData(sample) {
|
if isBinaryReadFileData(sample) {
|
||||||
return ErrorResult("file appears to be binary; use read_file for byte-based inspection")
|
return ErrorResult("file appears to be binary; switch read_file mode to 'bytes' for byte-based inspection")
|
||||||
}
|
}
|
||||||
|
|
||||||
reader := bufio.NewReaderSize(io.MultiReader(bytes.NewReader(sample), file), 32*1024)
|
reader := bufio.NewReaderSize(io.MultiReader(bytes.NewReader(sample), file), 32*1024)
|
||||||
|
|
|
||||||
|
|
@ -1135,11 +1135,11 @@ func TestReadFileLinesTool_BinaryFileRejected(t *testing.T) {
|
||||||
if !result.IsError {
|
if !result.IsError {
|
||||||
t.Fatalf("expected binary file rejection in line mode, got: %s", result.ForLLM)
|
t.Fatalf("expected binary file rejection in line mode, got: %s", result.ForLLM)
|
||||||
}
|
}
|
||||||
if !strings.Contains(result.ForLLM, "file appears to be binary") {
|
if !strings.Contains(result.ForLLM, "switch read_file mode to 'bytes'") {
|
||||||
t.Fatalf("expected binary file rejection message, got: %s", result.ForLLM)
|
t.Fatalf("expected binary file rejection message, got: %s", result.ForLLM)
|
||||||
}
|
}
|
||||||
if !strings.Contains(result.ForLLM, "use read_file") {
|
if !strings.Contains(result.ForLLM, "mode to 'bytes'") {
|
||||||
t.Fatalf("expected suggestion to use read_file, got: %s", result.ForLLM)
|
t.Fatalf("expected suggestion to switch read_file mode, got: %s", result.ForLLM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1190,7 +1190,10 @@ func TestReadFileLinesTool_NoTrailingNewline(t *testing.T) {
|
||||||
t.Fatalf("Execute() error = %s", result.ForLLM)
|
t.Fatalf("Execute() error = %s", result.ForLLM)
|
||||||
}
|
}
|
||||||
if !strings.Contains(result.ForLLM, "1|line 1\n2|line 2") {
|
if !strings.Contains(result.ForLLM, "1|line 1\n2|line 2") {
|
||||||
t.Fatalf("expected final line without trailing newline to be preserved, got: %s", result.ForLLM)
|
t.Fatalf(
|
||||||
|
"expected final line without trailing newline to be preserved, got: %s",
|
||||||
|
result.ForLLM,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if !strings.Contains(result.ForLLM, "[END OF FILE - no further content.]") {
|
if !strings.Contains(result.ForLLM, "[END OF FILE - no further content.]") {
|
||||||
t.Fatalf("expected EOF marker, got: %s", result.ForLLM)
|
t.Fatalf("expected EOF marker, got: %s", result.ForLLM)
|
||||||
|
|
@ -1215,10 +1218,16 @@ func TestReadFileLinesTool_ExactByteBudgetBoundaryIncludesPrefix(t *testing.T) {
|
||||||
t.Fatalf("Execute() error = %s", result.ForLLM)
|
t.Fatalf("Execute() error = %s", result.ForLLM)
|
||||||
}
|
}
|
||||||
if !strings.Contains(result.ForLLM, "1|1234567\n") {
|
if !strings.Contains(result.ForLLM, "1|1234567\n") {
|
||||||
t.Fatalf("expected first line to fit exactly in the byte budget with its prefix, got: %s", result.ForLLM)
|
t.Fatalf(
|
||||||
|
"expected first line to fit exactly in the byte budget with its prefix, got: %s",
|
||||||
|
result.ForLLM,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if strings.Contains(result.ForLLM, "2|") {
|
if strings.Contains(result.ForLLM, "2|") {
|
||||||
t.Fatalf("expected second line to be excluded once the exact output byte budget was reached, got: %s", result.ForLLM)
|
t.Fatalf(
|
||||||
|
"expected second line to be excluded once the exact output byte budget was reached, got: %s",
|
||||||
|
result.ForLLM,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if !strings.Contains(result.ForLLM, "file_bytes: 8 | output_bytes: 10") {
|
if !strings.Contains(result.ForLLM, "file_bytes: 8 | output_bytes: 10") {
|
||||||
t.Fatalf("expected separate file/output byte counters, got: %s", result.ForLLM)
|
t.Fatalf("expected separate file/output byte counters, got: %s", result.ForLLM)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue