Skip to content

fix(harness): mark optional FilesystemTool params as required=false#2227

Open
wzq-xzwj wants to merge 6 commits into
agentscope-ai:mainfrom
wzq-xzwj:fix/filesystemtool-optional-params
Open

fix(harness): mark optional FilesystemTool params as required=false#2227
wzq-xzwj wants to merge 6 commits into
agentscope-ai:mainfrom
wzq-xzwj:fix/filesystemtool-optional-params

Conversation

@wzq-xzwj

@wzq-xzwj wzq-xzwj commented Jul 15, 2026

Copy link
Copy Markdown

Summary

Several @ToolParam parameters on the harness built-in tools are documented as
optional (their descriptions say "Default: ...", "optional") and the underlying
implementation already handles missing / null / default values gracefully.
However, they are not annotated with required = false.

Because ToolParam.required() defaults to true, these parameters end up in the
generated JSON schema as required, contradicting both their descriptions and
the implementation. This misleads models into always supplying them.

Affected parameters:

Tool Param Description says Was in schema
read_file offset "Default: 0 (from beginning)" required
read_file limit "Default: 0 (all lines)" required
grep_files path dir/file to search required
grep_files glob "Optional file glob filter" required
glob_files path base dir to search from required
execute working_directory "(relative to workspace root, optional)" required
execute timeout "Timeout in seconds (default: 30)" required

Important: optional numeric params must be boxed types

Simply adding required = false to a primitive int parameter is not enough
— it introduces a runtime crash. When the model omits the argument, the framework
binds null and the reflective (MethodHandle) invocation fails with:

Cannot invoke "java.lang.Number.intValue()" because the return value of
"sun.invoke.util.ValueConversions.primitiveConversion(...)" is null

So this PR also changes read_file's offset/limit and execute's timeout
from int to Integer, applying null-safe defaults in the method body
(offset/limit -> 0, timeout -> 30). This mirrors edit_file's existing
Boolean replace_all parameter, which was already correctly boxed and optional.

Verified end-to-end: with the fix, read_file called without offset/limit
returns the file contents; before the fix it returned the intValue() NPE as a
tool error.

Implementation is already optional-safe

  • LocalFilesystem.grep(...): resolvePath(rc, path != null ? path : ".")
  • LocalFilesystem.glob(...): handles path == null -> falls back to cwd
  • ripgrepSearch / javaSearch: if (includeGlob != null && !includeGlob.isBlank())
  • LocalFilesystem.read(...): int startIdx = Math.max(0, offset), limit > 0 ? ... : all
  • ShellExecuteTool.execute(...): blank working_directory skipped; timeout > 0 ? timeout : 30

Change

  • Add required = false to the parameters listed above.
  • Box optional numeric params (int -> Integer) with null-safe defaults.
  • Formatting-only fix to SessionSearchTool so the module passes spotless:check.

Testing

  • mvn -pl agentscope-harness spotless:check -> BUILD SUCCESS.
  • End-to-end: agent calls read_file without offset/limit and gets file contents
    (previously crashed with an unboxing NPE).

@CLAassistant

CLAassistant commented Jul 15, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

read_file(offset,limit), grep_files(path,glob) and glob_files(path) are
documented as optional and the AbstractFilesystem implementation already
handles null/default values, but they lacked required=false and therefore
appeared as required in the generated tool schema. Align the annotations
with the descriptions and the implementation. Schema-only, no behavior
change. Mirrors the existing edit_file.replace_all annotation.
@wzq-xzwj wzq-xzwj force-pushed the fix/filesystemtool-optional-params branch from a89f2f6 to bd74c43 Compare July 15, 2026 10:35
…potless

The sessionId @ToolParam line exceeded the 100-column AOSP limit enforced by
spotless:check, causing the build to fail on every PR touching this module.
Wrap it as spotless expects. Formatting-only, no behavior change.
@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...gentscope/harness/agent/tool/ShellExecuteTool.java 50.00% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

The execute tool's working_directory (documented "optional") and timeout
(documented "default: 30") lacked required=false and therefore appeared as
required in the generated tool schema. The implementation already handles
their absence (blank working_directory is skipped; timeout falls back to 30
via `timeout > 0 ? timeout : 30`). Align the annotations with the
descriptions and the implementation. Schema-only, no behavior change.
@AgentScopeJavaBot AgentScopeJavaBot added bug Something isn't working area/harness agentscope-harness (test/runtime support) labels Jul 16, 2026

@AgentScopeJavaBot AgentScopeJavaBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Review

Aspect Count
🟢 Nitpick (信息性建议,不阻塞合并) 1
🟡 Recommended (建议修复,但不阻塞合并) 2

Overall Assessment: COMMENT — Schema-only fix with correct downstream handling; minor description improvements suggested for optional params.

@AgentScopeJavaBot AgentScopeJavaBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Review

Aspect Count
🟢 Nitpick (信息性建议,不阻塞合并) 1
🟡 Recommended (建议修复,但不阻塞合并) 2

Overall Assessment: COMMENT — Schema-only fix with correct downstream handling; minor description improvements suggested for optional params.

wzq-xzwj and others added 3 commits July 16, 2026 13:37
Marking a primitive int parameter as required=false is unsafe: when the model
omits it, the framework binds null and the reflective (MethodHandle) invocation
throws "Cannot invoke java.lang.Number.intValue() because the return value of
ValueConversions.primitiveConversion(...) is null".

Change read_file's offset/limit and execute's timeout from int to Integer and
apply null-safe defaults in the body (offset/limit -> 0, timeout -> 30). This
mirrors edit_file's existing Boolean replace_all parameter. Without this, the
required=false change alone makes these tools crash whenever the optional
argument is omitted.
Add unit tests covering the null-safe defaulting introduced when boxing the
optional numeric parameters:

- FilesystemToolTest: read_file with omitted offset/limit defaults both to 0;
  explicit values are passed through.
- ShellExecuteToolTest (new): execute with omitted timeout defaults to 30;
  explicit timeout is passed through; working_directory prefixes a cd.

Covers the previously-uncovered branches flagged by codecov/patch.
@wzq-xzwj

Copy link
Copy Markdown
Author

@jujn 请审核一下,实际使用中影响感觉还是很明显的,检查和自测均已通过。

@jujn

jujn commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

@jujn 请审核一下,实际使用中影响感觉还是很明显的,检查和自测均已通过。

最近任务比较多。可能会稍晚一些。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/harness agentscope-harness (test/runtime support) bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants