agentscope-ai / agentscope-ai/agentscope-java

[Bug]: read_file line pagination can return unbounded output for a single-line file

未關閉
#2,951 2 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
area/harness bug
主要語言
Java
星號
5.6k
分支
1.3k
平均合併
4 天 12 小時
30 天內合併 PR
77

描述

**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.

貢獻指南

開啟貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。