mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-02-25 03:44:09 +01:00
Build/Refactor: lint pre-commit hook and reformat repo to spec (#314)
* build/refactor: move lint/prettier packages to project root, install husky, add pre-commit hook * refactor: reformat files * build: put full eslintrc back with all rules
This commit is contained in:
parent
8d75b25104
commit
7fdc862042
157 changed files with 4836 additions and 2403 deletions
|
|
@ -1,16 +1,16 @@
|
|||
import React from 'react';
|
||||
import { Settings2 } from 'lucide-react';
|
||||
export default function AdjustButton({ onClick }) {
|
||||
const clickHandler = e => {
|
||||
const clickHandler = (e) => {
|
||||
e.preventDefault();
|
||||
onClick();
|
||||
};
|
||||
return (
|
||||
<button
|
||||
onClick={clickHandler}
|
||||
className="group absolute bottom-11 right-0 flex h-[100%] w-[50px] items-center justify-center bg-transparent p-1 text-gray-500 lg:bottom-0 lg:-right-11"
|
||||
className="group absolute bottom-11 right-0 flex h-[100%] w-[50px] items-center justify-center bg-transparent p-1 text-gray-500 lg:-right-11 lg:bottom-0"
|
||||
>
|
||||
<div className="m-1 mr-0 rounded-md p-2 pt-[10px] pb-[10px] group-hover:bg-gray-100 group-disabled:hover:bg-transparent dark:group-hover:bg-gray-900 dark:group-hover:text-gray-400 dark:group-disabled:hover:bg-transparent">
|
||||
<div className="m-1 mr-0 rounded-md p-2 pb-[10px] pt-[10px] group-hover:bg-gray-100 group-disabled:hover:bg-transparent dark:group-hover:bg-gray-900 dark:group-hover:text-gray-400 dark:group-disabled:hover:bg-transparent">
|
||||
<Settings2 size="1em" />
|
||||
</div>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ function BingAIOptions({ show }) {
|
|||
setSaveAsDialogShow(true);
|
||||
};
|
||||
|
||||
const setOption = param => newValue => {
|
||||
const setOption = param => (newValue) => {
|
||||
let update = {};
|
||||
update[param] = newValue;
|
||||
setConversation(prevState => ({
|
||||
|
|
@ -44,7 +44,10 @@ function BingAIOptions({ show }) {
|
|||
'transition-colors shadow-md rounded-md min-w-[75px] font-normal bg-white border-black/10 hover:border-black/10 focus:border-black/10 dark:border-black/10 dark:hover:border-black/10 dark:focus:border-black/10 border dark:bg-gray-700 text-black dark:text-white';
|
||||
const defaultClasses =
|
||||
'p-2 rounded-md min-w-[75px] font-normal bg-white/[.60] dark:bg-gray-700 text-black text-xs';
|
||||
const defaultSelected = cn(defaultClasses, 'font-medium data-[state=active]:text-white text-xs text-white');
|
||||
const defaultSelected = cn(
|
||||
defaultClasses,
|
||||
'font-medium data-[state=active]:text-white text-xs text-white'
|
||||
);
|
||||
const selectedClass = val => val + '-tab ' + defaultSelected;
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ function ChatGPTOptions() {
|
|||
|
||||
const models = endpointsConfig?.['chatGPTBrowser']?.['availableModels'] || [];
|
||||
|
||||
const setOption = param => newValue => {
|
||||
const setOption = param => (newValue) => {
|
||||
let update = {};
|
||||
update[param] = newValue;
|
||||
setConversation(prevState => ({
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@ import React from 'react';
|
|||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<div className="hidden px-3 pt-2 pb-1 text-center text-xs text-black/50 dark:text-white/50 md:block md:px-4 md:pt-3 md:pb-4">
|
||||
<div className="hidden px-3 pb-1 pt-2 text-center text-xs text-black/50 dark:text-white/50 md:block md:px-4 md:pb-4 md:pt-3">
|
||||
<a
|
||||
href="https://github.com/danny-avila/chatgpt-clone"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="underline"
|
||||
>
|
||||
{import.meta.env.VITE_APP_TITLE || "ChatGPT Clone"}
|
||||
{import.meta.env.VITE_APP_TITLE || 'ChatGPT Clone'}
|
||||
</a>
|
||||
. Serves and searches all conversations reliably. All AI convos under one house. Pay per call and not
|
||||
per month (cents compared to dollars).
|
||||
. Serves and searches all conversations reliably. All AI convos under one house. Pay per call
|
||||
and not per month (cents compared to dollars).
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ function GoogleOptions() {
|
|||
setSaveAsDialogShow(true);
|
||||
};
|
||||
|
||||
const setOption = param => newValue => {
|
||||
const setOption = param => (newValue) => {
|
||||
let update = {};
|
||||
update[param] = newValue;
|
||||
setConversation(prevState => ({
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ const alternateName = {
|
|||
azureOpenAI: 'Azure OpenAI',
|
||||
bingAI: 'Bing',
|
||||
chatGPTBrowser: 'ChatGPT',
|
||||
google: 'PaLM',
|
||||
}
|
||||
google: 'PaLM'
|
||||
};
|
||||
|
||||
export default function ModelItem({ endpoint, value, onSelect }) {
|
||||
const [setTokenDialogOpen, setSetTokenDialogOpen] = useState(false);
|
||||
|
|
@ -42,7 +42,7 @@ export default function ModelItem({ endpoint, value, onSelect }) {
|
|||
{isUserProvided ? (
|
||||
<button
|
||||
className="invisible m-0 mr-1 flex-initial rounded-md p-0 text-xs font-medium text-gray-400 hover:text-gray-700 group-hover:visible dark:font-normal dark:text-gray-400 dark:hover:text-gray-200"
|
||||
onClick={e => {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setSetTokenDialogOpen(true);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,7 @@ export default function EndpointItems({ endpoints, onSelect }) {
|
|||
return (
|
||||
<>
|
||||
{endpoints.map(endpoint => (
|
||||
<EndpointItem
|
||||
key={endpoint}
|
||||
value={endpoint}
|
||||
onSelect={onSelect}
|
||||
endpoint={endpoint}
|
||||
/>
|
||||
<EndpointItem key={endpoint} value={endpoint} onSelect={onSelect} endpoint={endpoint} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,16 +2,23 @@ import { useState } from 'react';
|
|||
import { FileUp } from 'lucide-react';
|
||||
import { cn } from '~/utils/';
|
||||
|
||||
const FileUpload = ({ onFileSelected, successText = null, invalidText = null, validator = null, text = null, id = '1' }) => {
|
||||
const FileUpload = ({
|
||||
onFileSelected,
|
||||
successText = null,
|
||||
invalidText = null,
|
||||
validator = null,
|
||||
text = null,
|
||||
id = '1'
|
||||
}) => {
|
||||
const [statusColor, setStatusColor] = useState('text-gray-600');
|
||||
const [status, setStatus] = useState(null);
|
||||
|
||||
const handleFileChange = event => {
|
||||
const handleFileChange = (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = e => {
|
||||
reader.onload = (e) => {
|
||||
const jsonData = JSON.parse(e.target.result);
|
||||
if (validator && !validator(jsonData)) {
|
||||
setStatus('invalid');
|
||||
|
|
@ -23,7 +30,7 @@ const FileUpload = ({ onFileSelected, successText = null, invalidText = null, va
|
|||
setStatus('success');
|
||||
setStatusColor('text-green-500 dark:text-green-500');
|
||||
}
|
||||
|
||||
|
||||
onFileSelected(jsonData);
|
||||
};
|
||||
reader.readAsText(file);
|
||||
|
|
@ -38,7 +45,9 @@ const FileUpload = ({ onFileSelected, successText = null, invalidText = null, va
|
|||
)}
|
||||
>
|
||||
<FileUp className="mr-1 flex w-[22px] items-center stroke-1" />
|
||||
<span className="flex text-xs ">{!status ? text || 'Import' : (status === 'success' ? successText : invalidText)}</span>
|
||||
<span className="flex text-xs ">
|
||||
{!status ? text || 'Import' : status === 'success' ? successText : invalidText}
|
||||
</span>
|
||||
<input
|
||||
id={`file-upload-${id}`}
|
||||
value=""
|
||||
|
|
|
|||
|
|
@ -4,7 +4,13 @@ import EditIcon from '../../svg/EditIcon.jsx';
|
|||
import TrashIcon from '../../svg/TrashIcon.jsx';
|
||||
import getIcon from '~/utils/getIcon';
|
||||
|
||||
export default function PresetItem({ preset = {}, value, onSelect, onChangePreset, onDeletePreset }) {
|
||||
export default function PresetItem({
|
||||
preset = {},
|
||||
value,
|
||||
onSelect,
|
||||
onChangePreset,
|
||||
onDeletePreset
|
||||
}) {
|
||||
const { endpoint } = preset;
|
||||
|
||||
const icon = getIcon({
|
||||
|
|
@ -53,7 +59,7 @@ export default function PresetItem({ preset = {}, value, onSelect, onChangePrese
|
|||
<div className="flex w-4 flex-1" />
|
||||
<button
|
||||
className="invisible m-0 mr-1 rounded-md p-2 text-gray-400 hover:text-gray-700 group-hover:visible dark:text-gray-400 dark:hover:text-gray-200 "
|
||||
onClick={e => {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
onChangePreset(preset);
|
||||
}}
|
||||
|
|
@ -62,7 +68,7 @@ export default function PresetItem({ preset = {}, value, onSelect, onChangePrese
|
|||
</button>
|
||||
<button
|
||||
className="invisible m-0 rounded-md text-gray-400 hover:text-gray-700 group-hover:visible dark:text-gray-400 dark:hover:text-gray-200 "
|
||||
onClick={e => {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
onDeletePreset(preset);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -39,21 +39,21 @@ export default function NewConversationMenu() {
|
|||
const deletePresetsMutation = useDeletePresetMutation();
|
||||
const createPresetMutation = useCreatePresetMutation();
|
||||
|
||||
const importPreset = jsonData => {
|
||||
const importPreset = (jsonData) => {
|
||||
createPresetMutation.mutate(
|
||||
{ ...jsonData },
|
||||
{
|
||||
onSuccess: data => {
|
||||
onSuccess: (data) => {
|
||||
setPresets(data);
|
||||
},
|
||||
onError: error => {
|
||||
onError: (error) => {
|
||||
console.error('Error uploading the preset:', error);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const onFileSelected = jsonData => {
|
||||
const onFileSelected = (jsonData) => {
|
||||
const jsonPreset = { ...cleanupPreset({ preset: jsonData, endpointsConfig }), presetId: null };
|
||||
importPreset(jsonPreset);
|
||||
};
|
||||
|
|
@ -80,7 +80,7 @@ export default function NewConversationMenu() {
|
|||
}, [conversation]);
|
||||
|
||||
// set the current model
|
||||
const onSelectEndpoint = newEndpoint => {
|
||||
const onSelectEndpoint = (newEndpoint) => {
|
||||
setMenuOpen(false);
|
||||
|
||||
if (!newEndpoint) return;
|
||||
|
|
@ -90,7 +90,7 @@ export default function NewConversationMenu() {
|
|||
};
|
||||
|
||||
// set the current model
|
||||
const onSelectPreset = newPreset => {
|
||||
const onSelectPreset = (newPreset) => {
|
||||
setMenuOpen(false);
|
||||
if (!newPreset) return;
|
||||
else {
|
||||
|
|
@ -98,7 +98,7 @@ export default function NewConversationMenu() {
|
|||
}
|
||||
};
|
||||
|
||||
const onChangePreset = preset => {
|
||||
const onChangePreset = (preset) => {
|
||||
setPresetModelVisible(true);
|
||||
setPreset(preset);
|
||||
};
|
||||
|
|
@ -107,7 +107,7 @@ export default function NewConversationMenu() {
|
|||
deletePresetsMutation.mutate({ arg: {} });
|
||||
};
|
||||
|
||||
const onDeletePreset = preset => {
|
||||
const onDeletePreset = (preset) => {
|
||||
deletePresetsMutation.mutate({ arg: preset });
|
||||
};
|
||||
|
||||
|
|
@ -121,10 +121,7 @@ export default function NewConversationMenu() {
|
|||
|
||||
return (
|
||||
<Dialog>
|
||||
<DropdownMenu
|
||||
open={menuOpen}
|
||||
onOpenChange={setMenuOpen}
|
||||
>
|
||||
<DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
|
|
@ -148,22 +145,18 @@ export default function NewConversationMenu() {
|
|||
className="overflow-y-auto"
|
||||
>
|
||||
{availableEndpoints.length ? (
|
||||
<EndpointItems
|
||||
endpoints={availableEndpoints}
|
||||
onSelect={onSelectEndpoint}
|
||||
/>
|
||||
<EndpointItems endpoints={availableEndpoints} onSelect={onSelectEndpoint} />
|
||||
) : (
|
||||
<DropdownMenuLabel className="dark:text-gray-300">No endpoint available.</DropdownMenuLabel>
|
||||
<DropdownMenuLabel className="dark:text-gray-300">
|
||||
No endpoint available.
|
||||
</DropdownMenuLabel>
|
||||
)}
|
||||
</DropdownMenuRadioGroup>
|
||||
|
||||
<div className="mt-6 w-full" />
|
||||
|
||||
<DropdownMenuLabel className="flex items-center dark:text-gray-300">
|
||||
<span
|
||||
className="cursor-pointer"
|
||||
onClick={() => setShowPresets(prev => !prev)}
|
||||
>
|
||||
<span className="cursor-pointer" onClick={() => setShowPresets(prev => !prev)}>
|
||||
{showPresets ? 'Hide ' : 'Show '} Presets
|
||||
</span>
|
||||
<div className="flex-1" />
|
||||
|
|
|
|||
|
|
@ -16,8 +16,15 @@ function OpenAIOptions() {
|
|||
|
||||
const [conversation, setConversation] = useRecoilState(store.conversation) || {};
|
||||
const { endpoint, conversationId } = conversation;
|
||||
const { model, chatGptLabel, promptPrefix, temperature, top_p, presence_penalty, frequency_penalty } =
|
||||
conversation;
|
||||
const {
|
||||
model,
|
||||
chatGptLabel,
|
||||
promptPrefix,
|
||||
temperature,
|
||||
top_p,
|
||||
presence_penalty,
|
||||
frequency_penalty
|
||||
} = conversation;
|
||||
|
||||
const endpointsConfig = useRecoilValue(store.endpointsConfig);
|
||||
|
||||
|
|
@ -36,7 +43,7 @@ function OpenAIOptions() {
|
|||
setSaveAsDialogShow(true);
|
||||
};
|
||||
|
||||
const setOption = param => newValue => {
|
||||
const setOption = param => (newValue) => {
|
||||
let update = {};
|
||||
update[param] = newValue;
|
||||
setConversation(prevState => ({
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ export default function RowButton({ onClick, children, text, className }) {
|
|||
type="button"
|
||||
>
|
||||
{children}
|
||||
<span className="hidden md:block">{text}</span>
|
||||
<span className="hidden md:block">{text}</span>
|
||||
{/* <RegenerateIcon />
|
||||
<span className="hidden md:block">Regenerate response</span> */}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@ function InputWithLabel({ value, onChange, label, id }) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Label
|
||||
htmlFor={id}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
<Label htmlFor={id} className="text-left text-sm font-medium">
|
||||
{label}
|
||||
<br />
|
||||
</Label>
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
|||
const helpText = {
|
||||
bingAI: (
|
||||
<small className="break-all text-gray-600">
|
||||
The Bing Access Token is the "_U" cookie from bing.com. Use dev tools or an extension while logged
|
||||
into the site to view it.
|
||||
The Bing Access Token is the "_U" cookie from bing.com. Use dev tools or an extension while
|
||||
logged into the site to view it.
|
||||
</small>
|
||||
),
|
||||
chatGPTBrowser: (
|
||||
|
|
@ -96,8 +96,8 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
|||
>
|
||||
Create a Service Account
|
||||
</a>
|
||||
. Make sure to click 'Create and Continue' to give at least the 'Vertex AI User' role. Lastly, create
|
||||
a JSON key to import here.
|
||||
. Make sure to click 'Create and Continue' to give at least the 'Vertex AI User' role.
|
||||
Lastly, create a JSON key to import here.
|
||||
</small>
|
||||
)
|
||||
};
|
||||
|
|
@ -122,10 +122,7 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={onOpenChange}
|
||||
>
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogTemplate
|
||||
title={`Set Token of ${endpoint}`}
|
||||
main={
|
||||
|
|
@ -137,7 +134,7 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
|||
text="Import Service Account JSON Key"
|
||||
successText="Successfully Imported Service Account JSON Key"
|
||||
invalidText="Invalid Service Account JSON Key, Did you import the correct file?"
|
||||
validator={credentials => {
|
||||
validator={(credentials) => {
|
||||
if (!credentials) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -168,7 +165,7 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
|||
|
||||
return true;
|
||||
}}
|
||||
onFileSelected={data => {
|
||||
onFileSelected={(data) => {
|
||||
setToken(JSON.stringify(data));
|
||||
}}
|
||||
/>
|
||||
|
|
@ -244,7 +241,9 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
|||
/>
|
||||
</>
|
||||
)}
|
||||
<small className="text-red-600">Your token will be sent to the server, but not saved.</small>
|
||||
<small className="text-red-600">
|
||||
Your token will be sent to the server, but not saved.
|
||||
</small>
|
||||
{helpText?.[endpoint]}
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default function SubmitButton({
|
|||
|
||||
const isTokenProvided = endpointsConfig?.[endpoint]?.userProvide ? !!getToken() : true;
|
||||
|
||||
const clickHandler = e => {
|
||||
const clickHandler = (e) => {
|
||||
e.preventDefault();
|
||||
submitMessage();
|
||||
};
|
||||
|
|
@ -101,12 +101,7 @@ export default function SubmitButton({
|
|||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<line
|
||||
x1="22"
|
||||
y1="2"
|
||||
x2="11"
|
||||
y2="13"
|
||||
/>
|
||||
<line x1="22" y1="2" x2="11" y2="13" />
|
||||
<polygon points="22 2 15 22 11 13 2 9 22 2" />
|
||||
</svg>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export default function TextChat({ isSearchView = false }) {
|
|||
// const bingStylesRef = useRef(null);
|
||||
const [showBingToneSetting, setShowBingToneSetting] = useState(false);
|
||||
|
||||
const isNotAppendable = (latestMessage?.unfinished & !isSubmitting) || latestMessage?.error;
|
||||
const isNotAppendable = latestMessage?.unfinished & !isSubmitting || latestMessage?.error;
|
||||
|
||||
// auto focus to input, when enter a conversation.
|
||||
useEffect(() => {
|
||||
|
|
@ -64,12 +64,12 @@ export default function TextChat({ isSearchView = false }) {
|
|||
setText('');
|
||||
};
|
||||
|
||||
const handleStopGenerating = e => {
|
||||
const handleStopGenerating = (e) => {
|
||||
e.preventDefault();
|
||||
stopGenerating();
|
||||
};
|
||||
|
||||
const handleKeyDown = e => {
|
||||
const handleKeyDown = (e) => {
|
||||
if (e.key === 'Enter' && isSubmitting) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@ export default function TextChat({ isSearchView = false }) {
|
|||
}
|
||||
};
|
||||
|
||||
const handleKeyUp = e => {
|
||||
const handleKeyUp = (e) => {
|
||||
if (e.keyCode === 8 && e.target.value.trim() === '') {
|
||||
setText(e.target.value);
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ export default function TextChat({ isSearchView = false }) {
|
|||
isComposing.current = false;
|
||||
};
|
||||
|
||||
const changeHandler = e => {
|
||||
const changeHandler = (e) => {
|
||||
const { value } = e.target;
|
||||
|
||||
setText(value);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue