🔧 chore: Update ESLint Config & Run Linter (#10986)
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run

This commit is contained in:
Danny Avila 2025-12-15 17:55:25 -05:00 committed by GitHub
parent e53619959d
commit f9060fa25f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 70 additions and 60 deletions

View file

@ -18,17 +18,17 @@ function generateShadcnPrompt(options) {
Here are the components that are available, along with how to import them, and how to use them:
${Object.values(components)
.map((component) => {
if (useXML) {
return dedent`
.map((component) => {
if (useXML) {
return dedent`
<component>
<name>${component.componentName}</name>
<import-instructions>${component.importDocs}</import-instructions>
<usage-instructions>${component.usageDocs}</usage-instructions>
</component>
`;
} else {
return dedent`
} else {
return dedent`
# ${component.componentName}
## Import Instructions
@ -37,9 +37,9 @@ function generateShadcnPrompt(options) {
## Usage Instructions
${component.usageDocs}
`;
}
})
.join('\n\n')}
}
})
.join('\n\n')}
`;
return systemPrompt;

View file

@ -232,7 +232,7 @@ class OpenWeather extends Tool {
if (['current_forecast', 'timestamp', 'daily_aggregation', 'overview'].includes(action)) {
if (typeof finalLat !== 'number' || typeof finalLon !== 'number') {
return 'Error: lat and lon are required and must be numbers for this action (or specify \'city\').';
return "Error: lat and lon are required and must be numbers for this action (or specify 'city').";
}
}
@ -243,7 +243,7 @@ class OpenWeather extends Tool {
let dt;
if (action === 'timestamp') {
if (!date) {
return 'Error: For timestamp action, a \'date\' in YYYY-MM-DD format is required.';
return "Error: For timestamp action, a 'date' in YYYY-MM-DD format is required.";
}
dt = this.convertDateToUnix(date);
}

View file

@ -43,7 +43,6 @@ afterEach(() => {
//TODO: This works/passes locally but http request tests fail with 404 in CI. Need to figure out why.
// eslint-disable-next-line jest/no-disabled-tests
describe.skip('GET /', () => {
it('should return 200 and the correct body', async () => {
process.env.APP_TITLE = 'Test Title';

View file

@ -3,7 +3,6 @@ const generateArtifactsPrompt = require('~/app/clients/prompts/artifacts');
const { getAssistant } = require('~/models/Assistant');
const buildOptions = async (endpoint, parsedBody) => {
const { promptPrefix, assistant_id, iconURL, greeting, spec, artifacts, ...modelOptions } =
parsedBody;
const endpointOption = removeNullishValues({

View file

@ -255,7 +255,7 @@ describe('processMessages', () => {
type: 'text',
text: {
value:
'The text you have uploaded is from the book "Harry Potter and the Philosopher\'s Stone" by J.K. Rowling. It follows the story of a young boy named Harry Potter who discovers that he is a wizard on his eleventh birthday. Here are some key points of the narrative:\n\n1. **Discovery and Invitation to Hogwarts**: Harry learns that he is a wizard and receives an invitation to attend Hogwarts School of Witchcraft and Wizardry【11:2†source】【11:4†source】.\n\n2. **Shopping for Supplies**: Hagrid takes Harry to Diagon Alley to buy his school supplies, including his wand from Ollivander\'s【11:9†source】【11:14†source】.\n\n3. **Introduction to Hogwarts**: Harry is introduced to Hogwarts, the magical school where he will learn about magic and discover more about his own background【11:12†source】【11:18†source】.\n\n4. **Meeting Friends and Enemies**: At Hogwarts, Harry makes friends like Ron Weasley and Hermione Granger, and enemies like Draco Malfoy【11:16†source】.\n\n5. **Uncovering the Mystery**: Harry, along with Ron and Hermione, uncovers the mystery of the Philosopher\'s Stone and its connection to the dark wizard Voldemort【11:1†source】【11:10†source】【11:7†source】.\n\nThese points highlight Harry\'s initial experiences in the magical world and set the stage for his adventures at Hogwarts.',
"The text you have uploaded is from the book \"Harry Potter and the Philosopher's Stone\" by J.K. Rowling. It follows the story of a young boy named Harry Potter who discovers that he is a wizard on his eleventh birthday. Here are some key points of the narrative:\n\n1. **Discovery and Invitation to Hogwarts**: Harry learns that he is a wizard and receives an invitation to attend Hogwarts School of Witchcraft and Wizardry【11:2†source】【11:4†source】.\n\n2. **Shopping for Supplies**: Hagrid takes Harry to Diagon Alley to buy his school supplies, including his wand from Ollivander's【11:9†source】【11:14†source】.\n\n3. **Introduction to Hogwarts**: Harry is introduced to Hogwarts, the magical school where he will learn about magic and discover more about his own background【11:12†source】【11:18†source】.\n\n4. **Meeting Friends and Enemies**: At Hogwarts, Harry makes friends like Ron Weasley and Hermione Granger, and enemies like Draco Malfoy【11:16†source】.\n\n5. **Uncovering the Mystery**: Harry, along with Ron and Hermione, uncovers the mystery of the Philosopher's Stone and its connection to the dark wizard Voldemort【11:1†source】【11:10†source】【11:7†source】.\n\nThese points highlight Harry's initial experiences in the magical world and set the stage for his adventures at Hogwarts.",
annotations: [
{
type: 'file_citation',
@ -424,7 +424,7 @@ These points highlight Harry's initial experiences in the magical world and set
type: 'text',
text: {
value:
'The text you have uploaded is from the book "Harry Potter and the Philosopher\'s Stone" by J.K. Rowling. It follows the story of a young boy named Harry Potter who discovers that he is a wizard on his eleventh birthday. Here are some key points of the narrative:\n\n1. **Discovery and Invitation to Hogwarts**: Harry learns that he is a wizard and receives an invitation to attend Hogwarts School of Witchcraft and Wizardry【11:2†source】【11:4†source】.\n\n2. **Shopping for Supplies**: Hagrid takes Harry to Diagon Alley to buy his school supplies, including his wand from Ollivander\'s【11:9†source】【11:14†source】.\n\n3. **Introduction to Hogwarts**: Harry is introduced to Hogwarts, the magical school where he will learn about magic and discover more about his own background【11:12†source】【11:18†source】.\n\n4. **Meeting Friends and Enemies**: At Hogwarts, Harry makes friends like Ron Weasley and Hermione Granger, and enemies like Draco Malfoy【11:16†source】.\n\n5. **Uncovering the Mystery**: Harry, along with Ron and Hermione, uncovers the mystery of the Philosopher\'s Stone and its connection to the dark wizard Voldemort【11:1†source】【11:10†source】【11:7†source】.\n\nThese points highlight Harry\'s initial experiences in the magical world and set the stage for his adventures at Hogwarts.',
"The text you have uploaded is from the book \"Harry Potter and the Philosopher's Stone\" by J.K. Rowling. It follows the story of a young boy named Harry Potter who discovers that he is a wizard on his eleventh birthday. Here are some key points of the narrative:\n\n1. **Discovery and Invitation to Hogwarts**: Harry learns that he is a wizard and receives an invitation to attend Hogwarts School of Witchcraft and Wizardry【11:2†source】【11:4†source】.\n\n2. **Shopping for Supplies**: Hagrid takes Harry to Diagon Alley to buy his school supplies, including his wand from Ollivander's【11:9†source】【11:14†source】.\n\n3. **Introduction to Hogwarts**: Harry is introduced to Hogwarts, the magical school where he will learn about magic and discover more about his own background【11:12†source】【11:18†source】.\n\n4. **Meeting Friends and Enemies**: At Hogwarts, Harry makes friends like Ron Weasley and Hermione Granger, and enemies like Draco Malfoy【11:16†source】.\n\n5. **Uncovering the Mystery**: Harry, along with Ron and Hermione, uncovers the mystery of the Philosopher's Stone and its connection to the dark wizard Voldemort【11:1†source】【11:10†source】【11:7†source】.\n\nThese points highlight Harry's initial experiences in the magical world and set the stage for his adventures at Hogwarts.",
annotations: [
{
type: 'file_citation',
@ -582,7 +582,7 @@ These points highlight Harry's initial experiences in the magical world and set
type: 'text',
text: {
value:
'This is a test ^1^ with pre-existing citation-like text. Here\'s a real citation【11:2†source】.',
"This is a test ^1^ with pre-existing citation-like text. Here's a real citation【11:2†source】.",
annotations: [
{
type: 'file_citation',
@ -610,7 +610,7 @@ These points highlight Harry's initial experiences in the magical world and set
});
const expectedText =
'This is a test ^1^ with pre-existing citation-like text. Here\'s a real citation^1^.\n\n^1.^ test.txt';
"This is a test ^1^ with pre-existing citation-like text. Here's a real citation^1^.\n\n^1.^ test.txt";
expect(result.text).toBe(expectedText);
expect(result.edited).toBe(true);

View file

@ -1,9 +1,9 @@
import { defaultNS, resources } from '~/locales/i18n';
declare module 'i18next' {
interface CustomTypeOptions {
defaultNS: typeof defaultNS;
resources: typeof resources.en;
strictKeyChecks: true
}
interface CustomTypeOptions {
defaultNS: typeof defaultNS;
resources: typeof resources.en;
strictKeyChecks: true;
}
}

View file

@ -156,7 +156,6 @@ test('renders registration form', () => {
);
});
// eslint-disable-next-line jest/no-commented-out-tests
// test('calls registerUser.mutate on registration', async () => {
// const mutate = jest.fn();
// const { getByTestId, getByRole, history } = setup({

View file

@ -100,7 +100,8 @@ function Artifacts() {
'ml-1 h-4 w-4 text-text-secondary transition-transform duration-300 md:ml-0.5',
isButtonExpanded && 'rotate-180',
)}
aria-hidden="true" />
aria-hidden="true"
/>
</Ariakit.MenuButton>
<Ariakit.Menu

View file

@ -92,7 +92,8 @@ export const columns: ColumnDef<TFile>[] = [
className="px-2 py-0 text-xs hover:bg-surface-hover sm:px-2 sm:py-2 sm:text-sm"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
aria-sort={ariaSort}
aria-label={localize('com_ui_name_sort')} aria-hidden="true"
aria-label={localize('com_ui_name_sort')}
aria-hidden="true"
aria-current={sortState ? 'true' : 'false'}
>
{localize('com_ui_name')}
@ -150,7 +151,8 @@ export const columns: ColumnDef<TFile>[] = [
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
className="px-2 py-0 text-xs hover:bg-surface-hover sm:px-2 sm:py-2 sm:text-sm"
aria-sort={ariaSort}
aria-label={localize('com_ui_date_sort')} aria-hidden="true"
aria-label={localize('com_ui_date_sort')}
aria-hidden="true"
aria-current={sortState ? 'true' : 'false'}
>
{localize('com_ui_date')}
@ -268,7 +270,8 @@ export const columns: ColumnDef<TFile>[] = [
className="px-2 py-0 text-xs hover:bg-surface-hover sm:px-2 sm:py-2 sm:text-sm"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
aria-sort={ariaSort}
aria-label={localize('com_ui_size_sort')} aria-hidden="true"
aria-label={localize('com_ui_size_sort')}
aria-hidden="true"
aria-current={sortState ? 'true' : 'false'}
>
{localize('com_ui_size')}

View file

@ -39,7 +39,7 @@ export default function StreamAudio({ index = 0 }) {
const { pauseGlobalAudio } = usePauseGlobalAudio();
const { conversationId: paramId } = useParams();
const queryParam = paramId === 'new' ? paramId : latestMessage?.conversationId ?? paramId ?? '';
const queryParam = paramId === 'new' ? paramId : (latestMessage?.conversationId ?? paramId ?? '');
const queryClient = useQueryClient();
const getMessages = useCallback(

View file

@ -33,7 +33,7 @@ export const data: TModelSpec[] = [
iconURL: EModelEndpoint.openAI, // Allow using project-included icons
preset: {
chatGptLabel: 'Vision Helper',
greeting: 'What\'s up!!',
greeting: "What's up!!",
endpoint: EModelEndpoint.openAI,
model: 'gpt-4-turbo',
promptPrefix:

View file

@ -55,7 +55,7 @@ const MenuItem: FC<MenuItemProps> = ({
>
<div className="flex grow items-center justify-between gap-2">
<div>
<div className={cn('flex items-center gap-1 ')}>
<div className={cn('flex items-center gap-1')}>
{icon != null ? icon : null}
<div className={cn('truncate', textClassName)}>
{title}
@ -72,7 +72,7 @@ const MenuItem: FC<MenuItemProps> = ({
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="icon-md block "
className="icon-md block"
>
<path
fillRule="evenodd"

View file

@ -15,7 +15,7 @@ export default function ProgressCircle({
className="absolute left-1/2 top-1/2 h-[23px] w-[23px] -translate-x-1/2 -translate-y-1/2 text-brand-purple"
>
<circle
className="origin-[50%_50%] -rotate-90 stroke-brand-purple/25 dark:stroke-brand-purple/50"
className="stroke-brand-purple/25 dark:stroke-brand-purple/50 origin-[50%_50%] -rotate-90"
strokeWidth="7.826086956521739"
fill="transparent"
r={radius}

View file

@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil';
import { useMessageProcess } from '~/hooks';
import type { TMessageProps } from '~/common';
import MessageRender from './ui/MessageRender';
// eslint-disable-next-line import/no-cycle
import MultiMessage from './MultiMessage';
import { cn } from '~/utils';
import store from '~/store';

View file

@ -1,7 +1,7 @@
import React from 'react';
import { useMessageProcess } from '~/hooks';
import type { TMessageProps } from '~/common';
// eslint-disable-next-line import/no-cycle
import MultiMessage from '~/components/Chat/Messages/MultiMessage';
import ContentRender from './ContentRender';
@ -64,7 +64,7 @@ export default function MessageContent(props: TMessageProps) {
</div>
</div>
) : (
<div className="m-auto justify-center p-4 py-2 md:gap-6 ">
<div className="m-auto justify-center p-4 py-2 md:gap-6">
<ContentRender {...props} />
</div>
)}

View file

@ -2,7 +2,7 @@ import { useEffect } from 'react';
import { useRecoilState } from 'recoil';
import type { TMessage } from 'librechat-data-provider';
import type { TMessageProps } from '~/common';
// eslint-disable-next-line import/no-cycle
import Message from './Message';
import store from '~/store';

View file

@ -33,9 +33,7 @@ export default function ActionsAuth({ disableOAuth }: { disableOAuth?: boolean }
</label>
</div>
<div className="border-token-border-medium flex rounded-lg border text-sm hover:cursor-pointer">
<div className="h-9 grow px-3 py-2">
{localize(getAuthLocalizationKey(type))}
</div>
<div className="h-9 grow px-3 py-2">{localize(getAuthLocalizationKey(type))}</div>
<div className="bg-token-border-medium w-px"></div>
<button type="button" color="neutral" className="flex items-center gap-2 px-3">
<svg

View file

@ -31,7 +31,7 @@ export default function useAddedHelpers({
store.messagesSiblingIdxFamily(latestMessage?.parentMessageId ?? null),
);
const queryParam = paramId === 'new' ? paramId : conversation?.conversationId ?? paramId ?? '';
const queryParam = paramId === 'new' ? paramId : (conversation?.conversationId ?? paramId ?? '');
const setMessages = useCallback(
(messages: TMessage[]) => {

View file

@ -1,4 +1,3 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import { EModelEndpoint, ImageDetail } from 'librechat-data-provider';
import type { ConversationData } from 'librechat-data-provider';
@ -98,7 +97,7 @@ export const convoData: ConversationData = {
promptPrefix: null,
resendFiles: false,
temperature: 1,
title: 'Write Einstein\'s Famous Equation in LaTeX',
title: "Write Einstein's Famous Equation in LaTeX",
top_p: 1,
updatedAt,
},

View file

@ -37,9 +37,7 @@ const connect = require('./connect');
const balanceConfig = getBalanceConfig(appConfig);
if (!balanceConfig?.enabled) {
console.red(
'Error: Balance is not enabled. Use librechat.yaml to enable it',
);
console.red('Error: Balance is not enabled. Use librechat.yaml to enable it');
silentExit(1);
}

View file

@ -78,7 +78,7 @@ const connect = require('./connect');
}
// Only prompt for emailVerified if it wasn't set via CLI
if (emailVerified === undefined){
if (emailVerified === undefined) {
const emailVerifiedInput = await askQuestion(`Email verified? (Y/n, default is Y):
If \`y\`, the user's email will be considered verified.

View file

@ -33,9 +33,7 @@ const connect = require('./connect');
const balanceConfig = getBalanceConfig();
if (!balanceConfig?.enabled) {
console.red(
'Error: Balance is not enabled. Use librechat.yaml to enable it',
);
console.red('Error: Balance is not enabled. Use librechat.yaml to enable it');
silentExit(1);
}

View file

@ -34,12 +34,15 @@ export default [
'packages/api/dist/**/*',
'packages/api/test_bundle/**/*',
'api/demo/**/*',
'packages/client/dist/**/*',
'packages/data-provider/types/**/*',
'packages/data-provider/dist/**/*',
'packages/data-provider/test_bundle/**/*',
'packages/data-schemas/dist/**/*',
'data-node/**/*',
'meili_data/**/*',
'**/node_modules/**/*',
'.devcontainer/**/*',
],
},
...fixupConfigRules(

View file

@ -250,6 +250,7 @@ export class BasicToolEndHandler implements EventHandler {
constructor(callback?: ToolEndCallback) {
this.callback = callback;
}
handle(
event: string,
data: StreamEventData | undefined,

View file

@ -9,5 +9,7 @@ export const mcpConfig = {
OAUTH_DETECTION_TIMEOUT: math(process.env.MCP_OAUTH_DETECTION_TIMEOUT ?? 5000),
CONNECTION_CHECK_TTL: math(process.env.MCP_CONNECTION_CHECK_TTL ?? 60000),
/** Idle timeout (ms) after which user connections are disconnected. Default: 15 minutes */
USER_CONNECTION_IDLE_TIMEOUT: math(process.env.MCP_USER_CONNECTION_IDLE_TIMEOUT ?? 15 * 60 * 1000),
USER_CONNECTION_IDLE_TIMEOUT: math(
process.env.MCP_USER_CONNECTION_IDLE_TIMEOUT ?? 15 * 60 * 1000,
),
};

View file

@ -9,7 +9,7 @@ interface OGDialogProps extends DialogPrimitive.DialogProps {
}
const Dialog = React.forwardRef<HTMLDivElement, OGDialogProps>(
({ children, triggerRef, triggerRefs, onOpenChange, ...props }, _ref) => {
({ children, triggerRef, triggerRefs, onOpenChange, ...props }) => {
const handleOpenChange = (open: boolean) => {
if (!open && triggerRef?.current) {
setTimeout(() => {
@ -122,7 +122,6 @@ const DialogContent = React.forwardRef<
{showCloseButton && (
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-ring-primary ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<X className="h-6 w-6" aria-hidden="true" />
{/* eslint-disable-next-line i18next/no-literal-string */}
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
)}

View file

@ -723,7 +723,9 @@ describe('AclEntry Model Tests', () => {
expect(permissionsMap.size).toBe(2); // Only resource1 and resource2 for user
expect(permissionsMap.get(resource1.toString())).toBe(PermissionBits.VIEW);
expect(permissionsMap.get(resource2.toString())).toBe(PermissionBits.VIEW | PermissionBits.EDIT);
expect(permissionsMap.get(resource2.toString())).toBe(
PermissionBits.VIEW | PermissionBits.EDIT,
);
expect(permissionsMap.get(resource3.toString())).toBeUndefined(); // User has no access
});
@ -772,7 +774,9 @@ describe('AclEntry Model Tests', () => {
expect(permissionsMap.size).toBe(2);
/** Resource1 should have VIEW | EDIT (from user + group) */
expect(permissionsMap.get(resource1.toString())).toBe(PermissionBits.VIEW | PermissionBits.EDIT);
expect(permissionsMap.get(resource1.toString())).toBe(
PermissionBits.VIEW | PermissionBits.EDIT,
);
/** Resource2 should have only VIEW (from user) */
expect(permissionsMap.get(resource2.toString())).toBe(PermissionBits.VIEW);
});
@ -847,7 +851,9 @@ describe('AclEntry Model Tests', () => {
);
expect(permissionsMap.size).toBe(2);
expect(permissionsMap.get(resource1.toString())).toBe(PermissionBits.VIEW | PermissionBits.EDIT);
expect(permissionsMap.get(resource1.toString())).toBe(
PermissionBits.VIEW | PermissionBits.EDIT,
);
expect(permissionsMap.get(resource2.toString())).toBe(PermissionBits.VIEW);
});
@ -903,7 +909,9 @@ describe('AclEntry Model Tests', () => {
/** Resources 20-29: USER VIEW | GROUP EDIT */
for (let i = 20; i < 30; i++) {
expect(permissionsMap.get(resources[i].toString())).toBe(PermissionBits.VIEW | PermissionBits.EDIT);
expect(permissionsMap.get(resources[i].toString())).toBe(
PermissionBits.VIEW | PermissionBits.EDIT,
);
}
/** Resources 30-39: GROUP EDIT only */

View file

@ -5,5 +5,8 @@ import type * as t from '~/types';
* Creates or returns the AgentCategory model using the provided mongoose instance and schema
*/
export function createAgentCategoryModel(mongoose: typeof import('mongoose')) {
return mongoose.models.AgentCategory || mongoose.model<t.IAgentCategory>('AgentCategory', agentCategorySchema);
return (
mongoose.models.AgentCategory ||
mongoose.model<t.IAgentCategory>('AgentCategory', agentCategorySchema)
);
}

View file

@ -38,7 +38,7 @@ const transactionSchema: Schema<ITransaction> = new Schema(
},
model: {
type: String,
index: true
index: true,
},
context: {
type: String,