Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 38 additions & 14 deletions packages/core/src/tools/agent/agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -635,22 +635,46 @@ describe('AgentTool', () => {
).toBeNull();
});

it('rejects an empty working_dir', () => {
expect(
agentTool.validateToolParams({
...validParams,
working_dir: '',
}),
).toMatch(/working_dir/i);
it('treats an empty working_dir as unset', () => {
const params = {
...validParams,
working_dir: '',
};

expect(agentTool.validateToolParams(params)).toBeNull();
expect(params.working_dir).toBeUndefined();
});

it('rejects a whitespace-only working_dir', () => {
expect(
agentTool.validateToolParams({
...validParams,
working_dir: ' ',
}),
).toMatch(/working_dir/i);
it('treats a whitespace-only working_dir as unset', () => {
const params = {
...validParams,
working_dir: ' ',
};

expect(agentTool.validateToolParams(params)).toBeNull();
expect(params.working_dir).toBeUndefined();
});

it('treats an empty working_dir as unset when isolation is set', () => {
const params = {
...validParams,
isolation: 'worktree' as const,
working_dir: '',
};

expect(agentTool.validateToolParams(params)).toBeNull();
expect(params.working_dir).toBeUndefined();
});

it('treats a whitespace-only working_dir as unset when isolation is set', () => {
const params = {
...validParams,
isolation: 'worktree' as const,
working_dir: ' ',
};

expect(agentTool.validateToolParams(params)).toBeNull();
expect(params.working_dir).toBeUndefined();
});

it('rejects working_dir combined with isolation', () => {
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/tools/agent/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,15 @@ assistant: Uses the ${ToolNames.AGENT} tool to launch the test-runner agent
}
}
}
// Some models emit an empty placeholder for the unused optional field.
// With isolation selected, normalize it away before downstream routing.
Comment on lines +1031 to +1032

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.

[Suggestion] Comment says "With isolation selected" but the normalization block below has no params.isolation condition — it runs unconditionally for all callers. Two of the four new tests confirm this by exercising normalization without isolation set.

Failure scenario: A future maintainer reads "With isolation selected" and assumes normalization should only fire when isolation is set. They add an isolation guard, reintroducing #7315 for non-isolation callers where models emit empty working_dir.

Suggested change
// Some models emit an empty placeholder for the unused optional field.
// With isolation selected, normalize it away before downstream routing.
// Some models emit an empty placeholder for the unused optional field.
// Normalize it away before downstream routing.

— qwen3.7-max via Qwen Code /review

if (
(typeof params.working_dir === 'string' &&
params.working_dir.trim().length === 0) ||
params.working_dir === null

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.

[Suggestion] The === null branch has no test coverage. All four new tests use empty or whitespace-only strings; none pass null.

Failure scenario: A future refactor simplifies the condition to only the string-trim check, dropping the null arm. Models sending working_dir: null would then hit the downstream typeof !== 'string' check and be rejected with "must be a non-empty string when set" — the exact spurious rejection this PR prevents.

Consider adding a test:

it('treats a null working_dir as unset', () => {
  const params = {
    ...validParams,
    working_dir: null as unknown as string,
  };
  expect(agentTool.validateToolParams(params)).toBeNull();
  expect(params.working_dir).toBeUndefined();
});

— qwen3.7-max via Qwen Code /review

) {
params.working_dir = undefined;
}

if (params.isolation !== undefined) {
if (params.isolation !== 'worktree') {
Expand Down
Loading