From 968430f63e5fd05f591ea11a9281b0d74c6cb792 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 20 Apr 2026 22:44:34 +0200 Subject: [PATCH] fix(tui): avoid cwd-path matches in @ autocomplete Only use fd --full-path for path queries so plain fuzzy @ autocomplete results no longer depend on whether the cwd path contains the query text. closes #2778 --- packages/tui/CHANGELOG.md | 1 + packages/tui/src/autocomplete.ts | 5 +++- packages/tui/test/autocomplete.test.ts | 33 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/tui/CHANGELOG.md b/packages/tui/CHANGELOG.md index be1caa7b..a22e79ab 100644 --- a/packages/tui/CHANGELOG.md +++ b/packages/tui/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed +- Fixed `@` autocomplete fuzzy search to stop matching against the full base path for plain queries, so worktree or cwd paths containing the query text no longer crowd out real results such as `@plan` suggestions ([#2778](https://github.com/badlogic/pi-mono/issues/2778)) - Fixed xterm `modifyOtherKeys` printable input so shifted uppercase letters insert correctly in the editor and shifted letter bindings parse and match consistently ([#3436](https://github.com/badlogic/pi-mono/issues/3436)) ## [0.67.68] - 2026-04-17 diff --git a/packages/tui/src/autocomplete.ts b/packages/tui/src/autocomplete.ts index 7137d5f4..9c950f0e 100644 --- a/packages/tui/src/autocomplete.ts +++ b/packages/tui/src/autocomplete.ts @@ -137,7 +137,6 @@ async function walkDirectoryWithFd( "f", "--type", "d", - "--full-path", "--hidden", "--exclude", ".git", @@ -147,6 +146,10 @@ async function walkDirectoryWithFd( ".git/**", ]; + if (toDisplayPath(query).includes("/")) { + args.push("--full-path"); + } + if (query) { args.push(buildFdPathQuery(query)); } diff --git a/packages/tui/test/autocomplete.test.ts b/packages/tui/test/autocomplete.test.ts index 7116f72f..5ca2a028 100644 --- a/packages/tui/test/autocomplete.test.ts +++ b/packages/tui/test/autocomplete.test.ts @@ -300,6 +300,39 @@ describe("CombinedAutocompleteProvider", () => { assert.ok(!values.some((value) => value === "@.git" || value.startsWith("@.git/"))); }); + test("returns the same @ suggestions when the cwd path contains the query", async () => { + const normalBaseDir = join(rootDir, "cwd-normal"); + const queryInPathBaseDir = join(rootDir, "cwd-plan-repro"); + mkdirSync(normalBaseDir, { recursive: true }); + mkdirSync(queryInPathBaseDir, { recursive: true }); + + const structure = { + dirs: ["packages/coding-agent/examples/extensions/plan-mode"], + files: { + "packages/coding-agent/examples/extensions/plan-mode/README.md": "readme", + "packages/pods/docs/plan.md": "plan", + }, + }; + setupFolder(normalBaseDir, structure); + setupFolder(queryInPathBaseDir, structure); + + const query = "@plan"; + const normalProvider = new CombinedAutocompleteProvider([], normalBaseDir, requireFdPath()); + const queryInPathProvider = new CombinedAutocompleteProvider([], queryInPathBaseDir, requireFdPath()); + + const normalResult = await getSuggestions(normalProvider, [query], 0, query.length); + const queryInPathResult = await getSuggestions(queryInPathProvider, [query], 0, query.length); + + const normalize = (result: Awaited>) => + (result?.items ?? []).map((item) => `${item.label} :: ${item.description ?? ""}`).sort(); + + assert.deepStrictEqual(normalize(queryInPathResult), normalize(normalResult)); + assert.ok( + normalize(normalResult).includes("plan-mode/ :: packages/coding-agent/examples/extensions/plan-mode"), + ); + assert.ok(normalize(normalResult).includes("plan.md :: packages/pods/docs/plan.md")); + }); + test("continues autocomplete inside quoted @ paths", async () => { setupFolder(baseDir, { files: {