diff --git a/packages/ui/src/components/ui/CommandPalette.tsx b/packages/ui/src/components/ui/CommandPalette.tsx index 2fe8a942..509d2734 100644 --- a/packages/ui/src/components/ui/CommandPalette.tsx +++ b/packages/ui/src/components/ui/CommandPalette.tsx @@ -352,7 +352,7 @@ export const CommandPalette: React.FC = () => { return; } let cancelled = false; - void searchFiles(currentRoot, trimmedQuery, 10, { type: 'file' }) + void searchFiles(currentRoot, trimmedQuery, 40, { type: 'file' }) .then((results) => { if (cancelled) return; setFileResults( diff --git a/packages/ui/src/components/ui/commandPaletteFilesState.test.ts b/packages/ui/src/components/ui/commandPaletteFilesState.test.ts index d542ef73..3c5de7d3 100644 --- a/packages/ui/src/components/ui/commandPaletteFilesState.test.ts +++ b/packages/ui/src/components/ui/commandPaletteFilesState.test.ts @@ -16,4 +16,27 @@ describe('commandPaletteFilesState', () => { expect(scoreCommandPaletteFiles(fileResults, 'alpha', freshKey, staleKey)).toEqual([]); expect(scoreCommandPaletteFiles(fileResults, 'alpha', freshKey, freshKey)).toHaveLength(1); }); + + test('matches directory segments of the relative path, not just the basename', () => { + const fileResults = [ + { name: 'index.md', path: '/kb/solo-is-a-team-size/index.md', relativePath: 'solo-is-a-team-size/index.md' }, + { name: 'index.md', path: '/kb/software-developer/index.md', relativePath: 'software-developer/index.md' }, + ]; + const key = buildCommandPaletteFileSearchKey('/kb', 'solo-is-a'); + + const scored = scoreCommandPaletteFiles(fileResults, 'solo-is-a', key, key); + expect(scored).toHaveLength(1); + expect(scored[0].item.relativePath).toBe('solo-is-a-team-size/index.md'); + }); + + test('ranks prefix path matches above later substring matches', () => { + const fileResults = [ + { name: 'index.md', path: '/kb/notes/solo/index.md', relativePath: 'notes/solo/index.md' }, + { name: 'index.md', path: '/kb/solo-is-a-team-size/index.md', relativePath: 'solo-is-a-team-size/index.md' }, + ]; + const key = buildCommandPaletteFileSearchKey('/kb', 'solo'); + + const scored = scoreCommandPaletteFiles(fileResults, 'solo', key, key); + expect(scored[0].item.relativePath).toBe('solo-is-a-team-size/index.md'); + }); }); diff --git a/packages/ui/src/components/ui/commandPaletteFilesState.ts b/packages/ui/src/components/ui/commandPaletteFilesState.ts index ac5a9b15..0ea03770 100644 --- a/packages/ui/src/components/ui/commandPaletteFilesState.ts +++ b/packages/ui/src/components/ui/commandPaletteFilesState.ts @@ -11,7 +11,7 @@ export const buildCommandPaletteFileSearchKey = ( return JSON.stringify([currentRoot, trimmedQuery]); }; -export const scoreCommandPaletteFiles = ( +export const scoreCommandPaletteFiles = ( fileResults: T[], trimmedQuery: string, fileSearchKey: string, @@ -21,7 +21,9 @@ export const scoreCommandPaletteFiles = ( return []; } - return scoreByFuzzyQuery(fileResults, trimmedQuery, (file) => file.name, { + // Score against the full relative path: queries like "solo-is-a" must match + // solo-is-a-team-size/index.md even though the basename is just index.md. + return scoreByFuzzyQuery(fileResults, trimmedQuery, (file) => file.relativePath || file.name, { limit: 10, threshold: 0.4, });