diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 73c0c926f..470137999 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -1,7 +1,6 @@ # Changelog ## [Unreleased] - ### Added - Added `todo.eager` setting to automatically create a comprehensive todo list after the first user message @@ -17,6 +16,7 @@ ### Fixed +- Fixed path resolution to accept bare directory names without trailing slashes in comma/space-separated path lists (e.g., `apps packages phases`) - Per-role `modelRoles` thinking selectors now propagate through commit/title helper model selection, legacy commit analysis, and agentic commit sessions while preserving default thinking inheritance when no role override is configured ## [13.10.1] - 2026-03-10 diff --git a/packages/coding-agent/src/tools/path-utils.ts b/packages/coding-agent/src/tools/path-utils.ts index 95f760a90..63bc1951c 100644 --- a/packages/coding-agent/src/tools/path-utils.ts +++ b/packages/coding-agent/src/tools/path-utils.ts @@ -349,7 +349,13 @@ async function areDelimitedTokensResolvable( } if (!allowBareExistingTokens && !looksLikeDelimitedPathToken(token)) { - return false; + // Bare names like "packages" don't look like path tokens syntactically, + // but may still be valid directory names. Check existence before rejecting. + const resolvedExactPath = resolveToCwd(token, cwd); + if (!(await pathExists(resolvedExactPath))) { + return false; + } + continue; } const basePath = parseBasePath(token); diff --git a/packages/coding-agent/test/tools/search-path-lists.test.ts b/packages/coding-agent/test/tools/search-path-lists.test.ts index 8d4c918ef..18d6e1889 100644 --- a/packages/coding-agent/test/tools/search-path-lists.test.ts +++ b/packages/coding-agent/test/tools/search-path-lists.test.ts @@ -194,4 +194,25 @@ describe("search tool path lists", () => { expect(details?.fileCount).toBe(6); expect(details?.scopePath).toBe("apps/, packages/, phases/"); }); + + it("grep accepts bare space-separated directory names (no trailing slash)", async () => { + const tools = await createTools(createTestSession(tempDir)); + const tool = tools.find(entry => entry.name === "grep"); + expect(tool).toBeDefined(); + if (!tool) throw new Error("Missing grep tool"); + + const result = await tool.execute("grep-bare-space-paths", { + pattern: "shared-needle", + path: "apps packages phases", + }); + const text = getText(result); + const details = result.details as { fileCount?: number; scopePath?: string } | undefined; + + expect(text).toContain("# apps"); + expect(text).toContain("# packages"); + expect(text).toContain("# phases"); + expect(text).not.toContain("# other"); + expect(details?.fileCount).toBe(3); + expect(details?.scopePath).toBe("apps, packages, phases"); + }); });