fix: normalize empty working_dir to unset when isolation:worktree is set on AgentTool - #7403
Conversation
…set on AgentTool Fixes QwenLM#7316
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed — no blockers. Suggestions are inline.
— qwen3.7-max via Qwen Code /review
| if ( | ||
| params.isolation === 'worktree' && | ||
| typeof params.working_dir === 'string' && | ||
| params.working_dir.trim().length === 0 | ||
| ) { | ||
| params.working_dir = undefined; | ||
| } |
There was a problem hiding this comment.
[Suggestion] validateToolParams mutates its input (params.working_dir = undefined), and the getToolDescription path in agent-core.ts passes the live args object through build(args) → validateToolParams. This means TOOL_CALL event emissions and pre-tool hooks silently see working_dir: undefined instead of the model-supplied "".
No functional breakage — the normalization is semantically correct — but event logs will differ from model output, which could confuse debugging (e.g. an investigator comparing model output to event logs would see an unexplained disappearance of the working_dir field).
Consider moving the normalization into createInvocation (and adjusting the validation block below to skip the empty-string check when isolation === 'worktree'), so validateToolParams stays a pure validator. Alternatively, structuredClone in getToolDescription would match the scheduler's hygiene.
— qwen3.7-max via Qwen Code /review
Review — normalize empty
|
doudouOUC
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅
— qwen3.7-max via Qwen Code /review
|
Thanks for this one as well, @wenshao - empty working_dir normalizing to unset makes worktree isolation behave predictably. |
What this PR does
Normalizes an empty
working_dirto unset whenisolation: "worktree"is requested on theagenttool, so a model that emitsworking_dir: ""can still start a worktree-isolated sub-agent.AgentTool.validateToolParams(packages/core/src/tools/agent/agent.ts) now treats an empty or whitespace-onlyworking_diras absent whenisolation === 'worktree', then defers to the existing isolation path. BecauseBaseDeclarativeTool.build()(packages/core/src/tools/tools.ts) validates and constructs the invocation from the sameparamsobject, unsettingworking_dirthere is enough;createInvocationalready branches onworking_dirtruthiness.Closes #7316
Why it's needed
Some OpenAI-compatible models emit
working_dir: ""even when asked to omit it. The current validation rejects any setworking_dirthat is empty before it checksisolation, so the call fails withParameter "working_dir" must be a non-empty string when set.and those models can never use worktree isolation. The repo's own triage bot confirmed this root cause on the issue and pointed at the exact function.Every other combination keeps its current behavior: an empty
working_dirwith noisolationis still rejected, and a non-emptyworking_diralongsiderun_in_background/forkis still rejected.Reviewer Test Plan
Covered by new unit tests in
agent.test.tsplus the manual steps below; the package's targeted unit tests pass locally.How to verify
agenttool withisolation: "worktree"andworking_dir: ""(or a whitespace-only string).Parameter "working_dir" must be a non-empty string when set.working_diris dropped and the sub-agent runs in an isolated worktree.working_dir: ""with noisolationis still rejected.Added
packages/core/src/tools/agent/agent.test.tscases covering the empty-working_dir+isolation: worktreeacceptance and the no-isolation rejection.Evidence (Before & After)
validateToolParamsreturns themust be a non-empty string when seterror, so the worktree path is never reached.validateToolParamsreturns no error for the empty-working_dir+ worktree case and the invocation proceeds withworking_dirunset.Tested on
Environment (optional)
Ran the package's targeted unit tests for the changed files locally.
Risk & Scope
isolation === 'worktree'plus an empty/whitespaceworking_dir.run_in_background/forkvalidation.Linked Issues
Closes #7316
AI was used for assistance.