agentscope-ai / agentscope-ai/agentscope-java
[Bug]: read_file line pagination can return unbounded output for a single-line file
- Linguagem predominante
- Java
- Estrelas
- 5.6k
- Forks
- 1.3k
- Merge médio
- 4d 12h
- PRs com merge (30d)
- 77
Descrição
**Describe the bug**
The Harness `read_file` tool paginates by line count through its `offset` and
`limit` parameters, but it does not impose a character or byte limit on the
returned content.
For a file containing one very large line, such as a multi-megabyte JSON file,
`read_file(path, offset=0, limit=1)` returns the entire line. Therefore, even a
small line limit can produce an unbounded tool result and exceed the model
context window.
This is particularly problematic because `read_file` is included in
`ToolResultEvictionConfig.DEFAULT_EXCLUDED_TOOLS`. The oversized result is
therefore not handled by `ToolResultEvictionMiddleware` and is passed directly
to the next model call.
Removing `read_file` from the exclusion set is not a complete workaround:
when the agent reads an evicted artifact and that read is itself oversized,
the result can be evicted into another artifact. The agent then receives
another placeholder instead of a reliably bounded chunk.
The ranged-read optimization merged in #2402 reduces memory usage by reading
only the requested lines, but a single requested line can still be arbitrarily
large.
**To Reproduce**
1. Create a workspace file containing a multi-megabyte single line:
```bash
{
printf '{"payload":"'
head -c 5000000 /dev/zero | tr '\0' 'a'
printf '"}'
} > large-single-line.json
```
2. Build a `HarnessAgent` with its default filesystem tools and default
`ToolResultEvictionConfig`.
3. Have the agent execute:
```text
read_file(
path="large-single-line.json",
offset=0,
limit=1
)
```
4. Observe that the tool result contains the complete multi-megabyte line,
despite `limit=1`.
5. The result bypasses tool-result eviction because `read_file` is excluded,
and the following model request can fail with a context-length error.
The same behavior can be reproduced directly through
`FilesystemTool.readFile(...)` and an `AbstractFilesystem` implementation.
**Expected behavior**
`read_file` should have a hard output-size boundary independent of line count.
A possible backward-compatible design would be:
- add an optional `max_chars` or `max_bytes` parameter;
- enforce a conservative default maximum;
- stop reading when either the line limit or size limit is reached;
- return explicit truncation metadata or guidance;
- provide a byte/character continuation offset for reading the remainder;
- preserve UTF-8 character boundaries;
- handle a single line larger than the limit without returning the whole line.
For example, the result could indicate:
```text
[Content truncated: returned bytes 0-65535.
Continue with byte_offset=65536.]
```
This would allow `read_file` to remain excluded from tool-result eviction while
still guaranteeing bounded model input.
`grep_files`, `glob_files`, and similar discovery tools already received
bounded-result handling on `main`; `read_file` needs an equivalent boundary
that also works for files without newline characters.
**Error messages**
There is no error at the tool layer. The oversized result is returned
successfully.
The subsequent model call may fail with an error similar to:
```text
context length exceeded
```
or emergency compaction may fail because the oversized tool result has already
entered the reasoning context.
**Environment (please complete the following information):**
- AgentScope-Java Version: 2.0.1; current `main` also appears affected
- Java Version: 21
- OS: Linux
**Additional context**
Related upstream work:
- #2319 fixed tool-result eviction for the immediate reasoning input and
persisted history.
- #2402 changed ranged file reads to stream requested lines, but did not add a
character/byte output limit.
- #2134 notes that recall tools may need exclusion from tool-result eviction to
avoid immediately evicting recalled content again.
This issue is specifically about making filesystem reads intrinsically bounded,
rather than relying on tool-result eviction to handle an already oversized
`read_file` result.
Guia de contribuição
Avaliação
Esta issue ainda não foi avaliada.