fix: keep @ file mention responsive on very large projects (#600)
Typing @ in the chat input to reference a file froze the app on huge workspaces. Two compounding causes: 1. The autocomplete hook fed fileFilterQuery straight into the React Query key, so every keystroke fired a new directory_suggestions request and a fresh BFS scan on the daemon. Added a 180 ms debounce that mirrors the existing pattern in new-workspace-screen so rapid typing coalesces into one request. 2. searchWorkspaceEntries only ignored node_modules, so dist, build, target, out, coverage, vendor and __pycache__ each consumed the 5,000-entry scan budget before any real source file was reached. Extended WORKSPACE_IGNORED_DIRECTORY_NAMES with those names and added a regression test that proves a deep source file is still reachable when those directories are full of bait entries. Refs #599 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
3ba4d09294
commit
2a4945ad0b
@@ -265,4 +265,34 @@ describe("searchWorkspaceEntries", () => {
|
||||
});
|
||||
expect(results.some((entry) => entry.path.startsWith("node_modules/"))).toBe(false);
|
||||
});
|
||||
|
||||
it("ignores common build/cache directories so large generated trees do not exhaust scan budget", async () => {
|
||||
mkdirSync(path.join(workspaceDir, "packages", "app", "src"), { recursive: true });
|
||||
writeFileSync(path.join(workspaceDir, "packages", "app", "src", "needle.ts"), "");
|
||||
|
||||
const heavyDirs = ["dist", "build", "target", "out", "coverage", "vendor", "__pycache__"];
|
||||
for (const heavyDir of heavyDirs) {
|
||||
for (let index = 0; index < 30; index += 1) {
|
||||
mkdirSync(path.join(workspaceDir, heavyDir, `bundle-${index}`), { recursive: true });
|
||||
writeFileSync(path.join(workspaceDir, heavyDir, `bundle-${index}`, "needle.ts"), "");
|
||||
}
|
||||
}
|
||||
|
||||
const results = await searchWorkspaceEntries({
|
||||
cwd: workspaceDir,
|
||||
query: "needle.ts",
|
||||
limit: 20,
|
||||
includeFiles: true,
|
||||
includeDirectories: true,
|
||||
maxEntriesScanned: 80,
|
||||
});
|
||||
|
||||
expect(results).toContainEqual({
|
||||
path: "packages/app/src/needle.ts",
|
||||
kind: "file",
|
||||
});
|
||||
for (const heavyDir of heavyDirs) {
|
||||
expect(results.some((entry) => entry.path.startsWith(`${heavyDir}/`))).toBe(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,7 +73,16 @@ const directoryListCache = new Map<string, DirectoryListCacheEntry>();
|
||||
const workspaceEntryListCache = new Map<string, WorkspaceEntryListCacheEntry>();
|
||||
const NO_SEGMENT_INDEX = Number.MAX_SAFE_INTEGER;
|
||||
const NO_MATCH_OFFSET = Number.MAX_SAFE_INTEGER;
|
||||
const WORKSPACE_IGNORED_DIRECTORY_NAMES = new Set(["node_modules"]);
|
||||
const WORKSPACE_IGNORED_DIRECTORY_NAMES = new Set([
|
||||
"node_modules",
|
||||
"dist",
|
||||
"build",
|
||||
"target",
|
||||
"out",
|
||||
"coverage",
|
||||
"vendor",
|
||||
"__pycache__",
|
||||
]);
|
||||
|
||||
export async function searchHomeDirectories(
|
||||
options: SearchHomeDirectoriesOptions,
|
||||
|
||||
Reference in New Issue
Block a user