chore: ran linting

This commit is contained in:
Anish Sarkar 2026-04-08 05:20:03 +05:30
parent d072ca60bb
commit 8455451ce1
20 changed files with 256 additions and 200 deletions

View file

@ -169,7 +169,9 @@ body:has(.suggestion-body) {
padding: 2px 4px;
line-height: 1;
border-radius: 4px;
transition: color 0.15s, background 0.15s;
transition:
color 0.15s,
background 0.15s;
}
.setup-dismiss:hover {

View file

@ -191,9 +191,9 @@ export const DocumentNode = React.memo(function DocumentNode({
<AlertCircle className="h-3.5 w-3.5 text-destructive" />
</span>
</TooltipTrigger>
<TooltipContent side="top">
{doc.status?.reason || "Processing failed"}
</TooltipContent>
<TooltipContent side="top">
{doc.status?.reason || "Processing failed"}
</TooltipContent>
</Tooltip>
);
}
@ -222,79 +222,83 @@ export const DocumentNode = React.memo(function DocumentNode({
</TooltipContent>
</Tooltip>
<span className="relative shrink-0 flex items-center justify-center h-6 w-6">
{getDocumentTypeIcon(
doc.document_type as DocumentTypeEnum,
"h-3.5 w-3.5 text-muted-foreground"
) && (
<span
className={cn(
"absolute inset-0 flex items-center justify-center transition-opacity pointer-events-none",
dropdownOpen ? "opacity-0" : "group-hover:opacity-0"
)}
>
{getDocumentTypeIcon(
doc.document_type as DocumentTypeEnum,
"h-3.5 w-3.5 text-muted-foreground"
)}
</span>
)}
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
<span className="relative shrink-0 flex items-center justify-center h-6 w-6">
{getDocumentTypeIcon(
doc.document_type as DocumentTypeEnum,
"h-3.5 w-3.5 text-muted-foreground"
) && (
<span
className={cn(
"hidden sm:inline-flex h-6 w-6 shrink-0 hover:bg-transparent",
dropdownOpen
? "opacity-100 bg-accent hover:bg-accent"
: "opacity-0 group-hover:opacity-100"
"absolute inset-0 flex items-center justify-center transition-opacity pointer-events-none",
dropdownOpen ? "opacity-0" : "group-hover:opacity-0"
)}
>
{getDocumentTypeIcon(
doc.document_type as DocumentTypeEnum,
"h-3.5 w-3.5 text-muted-foreground"
)}
</span>
)}
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className={cn(
"hidden sm:inline-flex h-6 w-6 shrink-0 hover:bg-transparent",
dropdownOpen
? "opacity-100 bg-accent hover:bg-accent"
: "opacity-0 group-hover:opacity-100"
)}
onClick={(e) => e.stopPropagation()}
>
<MoreHorizontal className="h-3.5 w-3.5 text-muted-foreground" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="w-40"
onClick={(e) => e.stopPropagation()}
>
<MoreHorizontal className="h-3.5 w-3.5 text-muted-foreground" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-40" onClick={(e) => e.stopPropagation()}>
<DropdownMenuItem onClick={() => onPreview(doc)} disabled={isProcessing}>
<Eye className="mr-2 h-4 w-4" />
Open
</DropdownMenuItem>
{isEditable && (
<DropdownMenuItem onClick={() => onEdit(doc)}>
<PenLine className="mr-2 h-4 w-4" />
Edit
<DropdownMenuItem onClick={() => onPreview(doc)} disabled={isProcessing}>
<Eye className="mr-2 h-4 w-4" />
Open
</DropdownMenuItem>
)}
<DropdownMenuItem onClick={() => onMove(doc)}>
<Move className="mr-2 h-4 w-4" />
Move to...
</DropdownMenuItem>
{onExport && (
<DropdownMenuSub>
<DropdownMenuSubTrigger disabled={isProcessing}>
<Download className="mr-2 h-4 w-4" />
Export
</DropdownMenuSubTrigger>
<DropdownMenuSubContent className="min-w-[180px]">
<ExportDropdownItems onExport={handleExport} exporting={exporting} />
</DropdownMenuSubContent>
</DropdownMenuSub>
)}
{onVersionHistory && isVersionableType(doc.document_type) && (
<DropdownMenuItem disabled={isProcessing} onClick={() => onVersionHistory(doc)}>
<History className="mr-2 h-4 w-4" />
Versions
{isEditable && (
<DropdownMenuItem onClick={() => onEdit(doc)}>
<PenLine className="mr-2 h-4 w-4" />
Edit
</DropdownMenuItem>
)}
<DropdownMenuItem onClick={() => onMove(doc)}>
<Move className="mr-2 h-4 w-4" />
Move to...
</DropdownMenuItem>
)}
<DropdownMenuItem disabled={isProcessing} onClick={() => onDelete(doc)}>
<Trash2 className="mr-2 h-4 w-4" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</span>
{onExport && (
<DropdownMenuSub>
<DropdownMenuSubTrigger disabled={isProcessing}>
<Download className="mr-2 h-4 w-4" />
Export
</DropdownMenuSubTrigger>
<DropdownMenuSubContent className="min-w-[180px]">
<ExportDropdownItems onExport={handleExport} exporting={exporting} />
</DropdownMenuSubContent>
</DropdownMenuSub>
)}
{onVersionHistory && isVersionableType(doc.document_type) && (
<DropdownMenuItem disabled={isProcessing} onClick={() => onVersionHistory(doc)}>
<History className="mr-2 h-4 w-4" />
Versions
</DropdownMenuItem>
)}
<DropdownMenuItem disabled={isProcessing} onClick={() => onDelete(doc)}>
<Trash2 className="mr-2 h-4 w-4" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</span>
</div>
</ContextMenuTrigger>

View file

@ -358,17 +358,17 @@ export const FolderNode = React.memo(function FolderNode({
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-40">
{isWatched && onRescan && (
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
handleRescan();
}}
>
<RefreshCw className={cn("mr-2 h-4 w-4", isRescanning && "animate-spin")} />
Re-scan
</DropdownMenuItem>
)}
{isWatched && onRescan && (
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
handleRescan();
}}
>
<RefreshCw className={cn("mr-2 h-4 w-4", isRescanning && "animate-spin")} />
Re-scan
</DropdownMenuItem>
)}
{isWatched && onStopWatching && (
<DropdownMenuItem
onClick={(e) => {
@ -407,15 +407,15 @@ export const FolderNode = React.memo(function FolderNode({
<Move className="mr-2 h-4 w-4" />
Move to...
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
onDelete(folder);
}}
>
<Trash2 className="mr-2 h-4 w-4" />
Delete
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
onDelete(folder);
}}
>
<Trash2 className="mr-2 h-4 w-4" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)}
@ -424,12 +424,12 @@ export const FolderNode = React.memo(function FolderNode({
{!isRenaming && contextMenuOpen && (
<ContextMenuContent className="w-40">
{isWatched && onRescan && (
<ContextMenuItem onClick={() => handleRescan()}>
<RefreshCw className={cn("mr-2 h-4 w-4", isRescanning && "animate-spin")} />
Re-scan
</ContextMenuItem>
)}
{isWatched && onRescan && (
<ContextMenuItem onClick={() => handleRescan()}>
<RefreshCw className={cn("mr-2 h-4 w-4", isRescanning && "animate-spin")} />
Re-scan
</ContextMenuItem>
)}
{isWatched && onStopWatching && (
<ContextMenuItem onClick={() => onStopWatching(folder)}>
<EyeOff className="mr-2 h-4 w-4" />
@ -448,10 +448,10 @@ export const FolderNode = React.memo(function FolderNode({
<Move className="mr-2 h-4 w-4" />
Move to...
</ContextMenuItem>
<ContextMenuItem onClick={() => onDelete(folder)}>
<Trash2 className="mr-2 h-4 w-4" />
Delete
</ContextMenuItem>
<ContextMenuItem onClick={() => onDelete(folder)}>
<Trash2 className="mr-2 h-4 w-4" />
Delete
</ContextMenuItem>
</ContextMenuContent>
)}
</ContextMenu>

View file

@ -7,7 +7,6 @@ import { useParams } from "next/navigation";
import { useTranslations } from "next-intl";
import { useCallback, useEffect, useMemo, useState } from "react";
import { toast } from "sonner";
import { DocumentsFilters } from "@/components/documents/DocumentsFilters";
import { sidebarSelectedDocumentsAtom } from "@/atoms/chat/mentioned-documents.atom";
import { connectorDialogOpenAtom } from "@/atoms/connector-dialog/connector-dialog.atoms";
import { connectorsAtom } from "@/atoms/connectors/connector-query.atoms";
@ -18,12 +17,13 @@ import { openEditorPanelAtom } from "@/atoms/editor/editor-panel.atom";
import { rightPanelCollapsedAtom } from "@/atoms/layout/right-panel.atom";
import { CreateFolderDialog } from "@/components/documents/CreateFolderDialog";
import type { DocumentNodeDoc } from "@/components/documents/DocumentNode";
import { DocumentsFilters } from "@/components/documents/DocumentsFilters";
import type { FolderDisplay } from "@/components/documents/FolderNode";
import { FolderPickerDialog } from "@/components/documents/FolderPickerDialog";
import { FolderWatchDialog, type SelectedFolder } from "@/components/sources/FolderWatchDialog";
import { FolderTreeView } from "@/components/documents/FolderTreeView";
import { VersionHistoryDialog } from "@/components/documents/version-history";
import { EXPORT_FILE_EXTENSIONS } from "@/components/shared/ExportMenuItems";
import { FolderWatchDialog, type SelectedFolder } from "@/components/sources/FolderWatchDialog";
import {
AlertDialog,
AlertDialogAction,
@ -109,8 +109,7 @@ export function DocumentsSidebar({
const folderPath = await api.selectFolder();
if (!folderPath) return;
const folderName =
folderPath.split("/").pop() || folderPath.split("\\").pop() || folderPath;
const folderName = folderPath.split("/").pop() || folderPath.split("\\").pop() || folderPath;
setWatchInitialFolder({ path: folderPath, name: folderName });
setFolderWatchOpen(true);
}, []);

View file

@ -21,9 +21,9 @@ import {
import { useParams, useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
import { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from "react";
import { getDocumentTypeLabel } from "@/components/documents/DocumentTypeIcon";
import { setTargetCommentIdAtom } from "@/atoms/chat/current-thread.atom";
import { convertRenderedToDisplay } from "@/components/chat-comments/comment-item/comment-item";
import { getDocumentTypeLabel } from "@/components/documents/DocumentTypeIcon";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/animated-tabs";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";

View file

@ -345,9 +345,7 @@ export function VisionConfigDialog({
<CommandInput
placeholder={selectedProvider?.example || "Search model name"}
value={formData.model_name}
onValueChange={(val) =>
setFormData((p) => ({ ...p, model_name: val }))
}
onValueChange={(val) => setFormData((p) => ({ ...p, model_name: val }))}
/>
<CommandList className="max-h-[300px]">
<CommandEmpty>

View file

@ -26,12 +26,16 @@ import { Progress } from "@/components/ui/progress";
import { Spinner } from "@/components/ui/spinner";
import { Switch } from "@/components/ui/switch";
import { useElectronAPI } from "@/hooks/use-platform";
import { getAcceptedFileTypes, getSupportedExtensions, getSupportedExtensionsSet } from "@/lib/supported-extensions";
import {
trackDocumentUploadFailure,
trackDocumentUploadStarted,
trackDocumentUploadSuccess,
} from "@/lib/posthog/events";
import {
getAcceptedFileTypes,
getSupportedExtensions,
getSupportedExtensionsSet,
} from "@/lib/supported-extensions";
interface DocumentUploadTabProps {
searchSpaceId: string;
@ -137,20 +141,24 @@ export function DocumentUploadTab({
if (!paths || paths.length === 0) return;
const fileDataList = await electronAPI.readLocalFiles(paths);
const filtered = fileDataList.filter((fd: { name: string; data: ArrayBuffer; mimeType: string }) => {
const ext = fd.name.includes(".") ? `.${fd.name.split(".").pop()?.toLowerCase()}` : "";
return ext !== "" && supportedExtensionsSet.has(ext);
});
const filtered = fileDataList.filter(
(fd: { name: string; data: ArrayBuffer; mimeType: string }) => {
const ext = fd.name.includes(".") ? `.${fd.name.split(".").pop()?.toLowerCase()}` : "";
return ext !== "" && supportedExtensionsSet.has(ext);
}
);
if (filtered.length === 0) {
toast.error(t("no_supported_files_in_folder"));
return;
}
const newFiles: FileWithId[] = filtered.map((fd: { name: string; data: ArrayBuffer; mimeType: string }) => ({
id: crypto.randomUUID?.() ?? `file-${Date.now()}-${Math.random().toString(36)}`,
file: new File([fd.data], fd.name, { type: fd.mimeType }),
}));
const newFiles: FileWithId[] = filtered.map(
(fd: { name: string; data: ArrayBuffer; mimeType: string }) => ({
id: crypto.randomUUID?.() ?? `file-${Date.now()}-${Math.random().toString(36)}`,
file: new File([fd.data], fd.name, { type: fd.mimeType }),
})
);
setFiles((prev) => [...prev, ...newFiles]);
}, [electronAPI, supportedExtensionsSet, t]);
@ -255,14 +263,14 @@ export function DocumentUploadTab({
className="dark:bg-neutral-800"
onClick={(e) => e.stopPropagation()}
>
<DropdownMenuItem onClick={handleBrowseFiles}>
<FileIcon className="h-4 w-4 mr-2" />
Files
</DropdownMenuItem>
<DropdownMenuItem onClick={() => folderInputRef.current?.click()}>
<FolderOpen className="h-4 w-4 mr-2" />
Folder
</DropdownMenuItem>
<DropdownMenuItem onClick={handleBrowseFiles}>
<FileIcon className="h-4 w-4 mr-2" />
Files
</DropdownMenuItem>
<DropdownMenuItem onClick={() => folderInputRef.current?.click()}>
<FolderOpen className="h-4 w-4 mr-2" />
Folder
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
@ -320,8 +328,8 @@ export function DocumentUploadTab({
{/* MOBILE DROP ZONE */}
<div className="sm:hidden">
{hasContent ? (
isElectron ? (
{hasContent ? (
isElectron ? (
<div className="w-full">{renderBrowseButton({ compact: true, fullWidth: true })}</div>
) : (
<button

View file

@ -55,10 +55,7 @@ export function FolderWatchDialog({
}
}, [open, initialFolder]);
const supportedExtensions = useMemo(
() => Array.from(getSupportedExtensionsSet()),
[]
);
const supportedExtensions = useMemo(() => Array.from(getSupportedExtensionsSet()), []);
const handleSelectFolder = useCallback(async () => {
const api = window.electronAPI;
@ -67,8 +64,7 @@ export function FolderWatchDialog({
const folderPath = await api.selectFolder();
if (!folderPath) return;
const folderName =
folderPath.split("/").pop() || folderPath.split("\\").pop() || folderPath;
const folderName = folderPath.split("/").pop() || folderPath.split("\\").pop() || folderPath;
setSelectedFolder({ path: folderPath, name: folderName });
}, []);
@ -87,8 +83,7 @@ export function FolderWatchDialog({
file_extensions: supportedExtensions,
});
const rootFolderId =
(result as { root_folder_id?: number })?.root_folder_id ?? null;
const rootFolderId = (result as { root_folder_id?: number })?.root_folder_id ?? null;
await api.addWatchedFolder({
path: selectedFolder.path,
@ -110,7 +105,14 @@ export function FolderWatchDialog({
} finally {
setSubmitting(false);
}
}, [selectedFolder, searchSpaceId, shouldSummarize, supportedExtensions, onOpenChange, onSuccess]);
}, [
selectedFolder,
searchSpaceId,
shouldSummarize,
supportedExtensions,
onOpenChange,
onSuccess,
]);
const handleOpenChange = useCallback(
(nextOpen: boolean) => {
@ -128,18 +130,14 @@ export function FolderWatchDialog({
<DialogContent className="sm:max-w-md select-none">
<DialogHeader>
<DialogTitle>Watch Local Folder</DialogTitle>
<DialogDescription>
Select a folder to sync and watch for changes.
</DialogDescription>
<DialogDescription>Select a folder to sync and watch for changes.</DialogDescription>
</DialogHeader>
<div className="space-y-3 pt-2">
{selectedFolder ? (
<div className="flex items-center gap-2 py-1.5 pl-4 pr-2 rounded-md bg-slate-400/5 dark:bg-white/5 overflow-hidden">
<div className="min-w-0 flex-1 select-text">
<p className="text-sm font-medium break-all line-clamp-2">
{selectedFolder.name}
</p>
<p className="text-sm font-medium break-all line-clamp-2">{selectedFolder.name}</p>
<p className="text-xs text-muted-foreground break-all line-clamp-2">
{selectedFolder.path}
</p>
@ -173,20 +171,11 @@ export function FolderWatchDialog({
Improves search quality but adds latency
</p>
</div>
<Switch
checked={shouldSummarize}
onCheckedChange={setShouldSummarize}
/>
<Switch checked={shouldSummarize} onCheckedChange={setShouldSummarize} />
</div>
<Button
className="w-full relative"
onClick={handleSubmit}
disabled={submitting}
>
<span className={submitting ? "invisible" : ""}>
Start Folder Sync
</span>
<Button className="w-full relative" onClick={handleSubmit} disabled={submitting}>
<span className={submitting ? "invisible" : ""}>Start Folder Sync</span>
{submitting && (
<span className="absolute inset-0 flex items-center justify-center">
<Spinner size="sm" />

View file

@ -107,22 +107,62 @@ export const VISION_MODELS: LLMModel[] = [
{ value: "gpt-4o", label: "GPT-4o", provider: "OPENAI", contextWindow: "128K" },
{ value: "gpt-4o-mini", label: "GPT-4o Mini", provider: "OPENAI", contextWindow: "128K" },
{ value: "gpt-4-turbo", label: "GPT-4 Turbo", provider: "OPENAI", contextWindow: "128K" },
{ value: "claude-sonnet-4-20250514", label: "Claude Sonnet 4", provider: "ANTHROPIC", contextWindow: "200K" },
{ value: "claude-3-7-sonnet-20250219", label: "Claude 3.7 Sonnet", provider: "ANTHROPIC", contextWindow: "200K" },
{ value: "claude-3-5-sonnet-20241022", label: "Claude 3.5 Sonnet", provider: "ANTHROPIC", contextWindow: "200K" },
{ value: "claude-3-opus-20240229", label: "Claude 3 Opus", provider: "ANTHROPIC", contextWindow: "200K" },
{ value: "claude-3-haiku-20240307", label: "Claude 3 Haiku", provider: "ANTHROPIC", contextWindow: "200K" },
{
value: "claude-sonnet-4-20250514",
label: "Claude Sonnet 4",
provider: "ANTHROPIC",
contextWindow: "200K",
},
{
value: "claude-3-7-sonnet-20250219",
label: "Claude 3.7 Sonnet",
provider: "ANTHROPIC",
contextWindow: "200K",
},
{
value: "claude-3-5-sonnet-20241022",
label: "Claude 3.5 Sonnet",
provider: "ANTHROPIC",
contextWindow: "200K",
},
{
value: "claude-3-opus-20240229",
label: "Claude 3 Opus",
provider: "ANTHROPIC",
contextWindow: "200K",
},
{
value: "claude-3-haiku-20240307",
label: "Claude 3 Haiku",
provider: "ANTHROPIC",
contextWindow: "200K",
},
{ value: "gemini-2.5-flash", label: "Gemini 2.5 Flash", provider: "GOOGLE", contextWindow: "1M" },
{ value: "gemini-2.5-pro", label: "Gemini 2.5 Pro", provider: "GOOGLE", contextWindow: "1M" },
{ value: "gemini-2.0-flash", label: "Gemini 2.0 Flash", provider: "GOOGLE", contextWindow: "1M" },
{ value: "gemini-1.5-pro", label: "Gemini 1.5 Pro", provider: "GOOGLE", contextWindow: "1M" },
{ value: "gemini-1.5-flash", label: "Gemini 1.5 Flash", provider: "GOOGLE", contextWindow: "1M" },
{ value: "pixtral-large-latest", label: "Pixtral Large", provider: "MISTRAL", contextWindow: "128K" },
{
value: "pixtral-large-latest",
label: "Pixtral Large",
provider: "MISTRAL",
contextWindow: "128K",
},
{ value: "pixtral-12b-2409", label: "Pixtral 12B", provider: "MISTRAL", contextWindow: "128K" },
{ value: "grok-2-vision-1212", label: "Grok 2 Vision", provider: "XAI", contextWindow: "32K" },
{ value: "llava", label: "LLaVA", provider: "OLLAMA" },
{ value: "bakllava", label: "BakLLaVA", provider: "OLLAMA" },
{ value: "llava-llama3", label: "LLaVA Llama 3", provider: "OLLAMA" },
{ value: "llama-4-scout-17b-16e-instruct", label: "Llama 4 Scout 17B", provider: "GROQ", contextWindow: "128K" },
{ value: "meta-llama/Llama-4-Scout-17B-16E-Instruct", label: "Llama 4 Scout 17B", provider: "TOGETHER_AI", contextWindow: "128K" },
{
value: "llama-4-scout-17b-16e-instruct",
label: "Llama 4 Scout 17B",
provider: "GROQ",
contextWindow: "128K",
},
{
value: "meta-llama/Llama-4-Scout-17B-16E-Instruct",
label: "Llama 4 Scout 17B",
provider: "TOGETHER_AI",
contextWindow: "128K",
},
];

View file

@ -80,9 +80,7 @@ export function getAcceptedFileTypes(): Record<string, string[]> {
return FILE_TYPE_CONFIG[etlService || "default"] || FILE_TYPE_CONFIG.default;
}
export function getSupportedExtensions(
acceptedFileTypes?: Record<string, string[]>
): string[] {
export function getSupportedExtensions(acceptedFileTypes?: Record<string, string[]>): string[] {
const types = acceptedFileTypes ?? getAcceptedFileTypes();
return Array.from(new Set(Object.values(types).flat())).sort();
}