Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import Fuse, { type IFuseOptions } from "fuse.js";
import { useDraftStore } from "../stores/draftStore";
import type { CommandSuggestionItem, FileSuggestionItem } from "../types";

const FILE_LIMIT = 5;
const FILE_DISPLAY_LIMIT = 25;
const FILE_FETCH_LIMIT = 100;
const COMMAND_LIMIT = 5;

const FUSE_OPTIONS: IFuseOptions<AvailableCommand> = {
const COMMAND_FUSE_OPTIONS: IFuseOptions<AvailableCommand> = {
keys: [
{ name: "name", weight: 0.7 },
{ name: "description", weight: 0.3 },
Expand All @@ -18,6 +19,20 @@ const FUSE_OPTIONS: IFuseOptions<AvailableCommand> = {
includeScore: true,
};

interface FileItem {
path: string;
name: string;
}

const FILE_FUSE_OPTIONS: IFuseOptions<FileItem> = {
keys: [
{ name: "name", weight: 0.7 },
{ name: "path", weight: 0.3 },
],
threshold: 0.4,
includeScore: true,
};

function searchCommands(
commands: AvailableCommand[],
query: string,
Expand All @@ -26,7 +41,7 @@ function searchCommands(
return commands.slice(0, COMMAND_LIMIT);
}

const fuse = new Fuse(commands, FUSE_OPTIONS);
const fuse = new Fuse(commands, COMMAND_FUSE_OPTIONS);
const results = fuse.search(query, { limit: COMMAND_LIMIT * 2 });

const lowerQuery = query.toLowerCase();
Expand All @@ -42,6 +57,27 @@ function searchCommands(
return results.slice(0, COMMAND_LIMIT).map((result) => result.item);
}

function searchFiles(files: FileItem[], query: string): FileItem[] {
if (!query.trim()) {
return files.slice(0, FILE_DISPLAY_LIMIT);
}

const fuse = new Fuse(files, FILE_FUSE_OPTIONS);
const results = fuse.search(query, { limit: FILE_DISPLAY_LIMIT * 2 });

const lowerQuery = query.toLowerCase();
results.sort((a, b) => {
const aStartsWithQuery = a.item.name.toLowerCase().startsWith(lowerQuery);
const bStartsWithQuery = b.item.name.toLowerCase().startsWith(lowerQuery);

if (aStartsWithQuery && !bStartsWithQuery) return -1;
if (!aStartsWithQuery && bStartsWithQuery) return 1;
return (a.score ?? 0) - (b.score ?? 0);
});

return results.slice(0, FILE_DISPLAY_LIMIT).map((result) => result.item);
}

export async function getFileSuggestions(
sessionId: string,
query: string,
Expand All @@ -55,19 +91,26 @@ export async function getFileSuggestions(
const results = await trpcVanilla.fs.listRepoFiles.query({
repoPath,
query,
limit: FILE_LIMIT,
limit: FILE_FETCH_LIMIT,
});

return results
const files: FileItem[] = results
.filter(
(file: MentionItem): file is MentionItem & { path: string } =>
!!file.path,
)
.map((file) => ({
id: file.path,
label: file.path,
path: file.path,
name: file.path.split("/").pop() ?? file.path,
}));

const matched = searchFiles(files, query);

return matched.map((file) => ({
id: file.path,
label: file.path,
path: file.path,
}));
}

export function getCommandSuggestions(
Expand Down