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

View file

@ -232,7 +232,7 @@ class OpenWeather extends Tool {
if (['current_forecast', 'timestamp', 'daily_aggregation', 'overview'].includes(action)) { if (['current_forecast', 'timestamp', 'daily_aggregation', 'overview'].includes(action)) {
if (typeof finalLat !== 'number' || typeof finalLon !== 'number') { 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; let dt;
if (action === 'timestamp') { if (action === 'timestamp') {
if (!date) { 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); 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. //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 /', () => { describe.skip('GET /', () => {
it('should return 200 and the correct body', async () => { it('should return 200 and the correct body', async () => {
process.env.APP_TITLE = 'Test Title'; 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 { getAssistant } = require('~/models/Assistant');
const buildOptions = async (endpoint, parsedBody) => { const buildOptions = async (endpoint, parsedBody) => {
const { promptPrefix, assistant_id, iconURL, greeting, spec, artifacts, ...modelOptions } = const { promptPrefix, assistant_id, iconURL, greeting, spec, artifacts, ...modelOptions } =
parsedBody; parsedBody;
const endpointOption = removeNullishValues({ const endpointOption = removeNullishValues({

View file

@ -255,7 +255,7 @@ describe('processMessages', () => {
type: 'text', type: 'text',
text: { text: {
value: 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: [ annotations: [
{ {
type: 'file_citation', type: 'file_citation',
@ -424,7 +424,7 @@ These points highlight Harry's initial experiences in the magical world and set
type: 'text', type: 'text',
text: { text: {
value: 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: [ annotations: [
{ {
type: 'file_citation', type: 'file_citation',
@ -582,7 +582,7 @@ These points highlight Harry's initial experiences in the magical world and set
type: 'text', type: 'text',
text: { text: {
value: 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: [ annotations: [
{ {
type: 'file_citation', type: 'file_citation',
@ -610,7 +610,7 @@ These points highlight Harry's initial experiences in the magical world and set
}); });
const expectedText = 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.text).toBe(expectedText);
expect(result.edited).toBe(true); expect(result.edited).toBe(true);

View file

@ -1,9 +1,9 @@
import { defaultNS, resources } from '~/locales/i18n'; import { defaultNS, resources } from '~/locales/i18n';
declare module 'i18next' { declare module 'i18next' {
interface CustomTypeOptions { interface CustomTypeOptions {
defaultNS: typeof defaultNS; defaultNS: typeof defaultNS;
resources: typeof resources.en; resources: typeof resources.en;
strictKeyChecks: true 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 () => { // test('calls registerUser.mutate on registration', async () => {
// const mutate = jest.fn(); // const mutate = jest.fn();
// const { getByTestId, getByRole, history } = setup({ // 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', 'ml-1 h-4 w-4 text-text-secondary transition-transform duration-300 md:ml-0.5',
isButtonExpanded && 'rotate-180', isButtonExpanded && 'rotate-180',
)} )}
aria-hidden="true" /> aria-hidden="true"
/>
</Ariakit.MenuButton> </Ariakit.MenuButton>
<Ariakit.Menu <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" 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')} onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
aria-sort={ariaSort} 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'} aria-current={sortState ? 'true' : 'false'}
> >
{localize('com_ui_name')} {localize('com_ui_name')}
@ -150,7 +151,8 @@ export const columns: ColumnDef<TFile>[] = [
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')} 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" className="px-2 py-0 text-xs hover:bg-surface-hover sm:px-2 sm:py-2 sm:text-sm"
aria-sort={ariaSort} 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'} aria-current={sortState ? 'true' : 'false'}
> >
{localize('com_ui_date')} {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" 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')} onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
aria-sort={ariaSort} 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'} aria-current={sortState ? 'true' : 'false'}
> >
{localize('com_ui_size')} {localize('com_ui_size')}

View file

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

View file

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

View file

@ -55,7 +55,7 @@ const MenuItem: FC<MenuItemProps> = ({
> >
<div className="flex grow items-center justify-between gap-2"> <div className="flex grow items-center justify-between gap-2">
<div> <div>
<div className={cn('flex items-center gap-1 ')}> <div className={cn('flex items-center gap-1')}>
{icon != null ? icon : null} {icon != null ? icon : null}
<div className={cn('truncate', textClassName)}> <div className={cn('truncate', textClassName)}>
{title} {title}
@ -72,7 +72,7 @@ const MenuItem: FC<MenuItemProps> = ({
viewBox="0 0 24 24" viewBox="0 0 24 24"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
className="icon-md block " className="icon-md block"
> >
<path <path
fillRule="evenodd" 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" className="absolute left-1/2 top-1/2 h-[23px] w-[23px] -translate-x-1/2 -translate-y-1/2 text-brand-purple"
> >
<circle <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" strokeWidth="7.826086956521739"
fill="transparent" fill="transparent"
r={radius} r={radius}

View file

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

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { useMessageProcess } from '~/hooks'; import { useMessageProcess } from '~/hooks';
import type { TMessageProps } from '~/common'; import type { TMessageProps } from '~/common';
// eslint-disable-next-line import/no-cycle
import MultiMessage from '~/components/Chat/Messages/MultiMessage'; import MultiMessage from '~/components/Chat/Messages/MultiMessage';
import ContentRender from './ContentRender'; import ContentRender from './ContentRender';
@ -64,7 +64,7 @@ export default function MessageContent(props: TMessageProps) {
</div> </div>
</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} /> <ContentRender {...props} />
</div> </div>
)} )}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -9,5 +9,7 @@ export const mcpConfig = {
OAUTH_DETECTION_TIMEOUT: math(process.env.MCP_OAUTH_DETECTION_TIMEOUT ?? 5000), OAUTH_DETECTION_TIMEOUT: math(process.env.MCP_OAUTH_DETECTION_TIMEOUT ?? 5000),
CONNECTION_CHECK_TTL: math(process.env.MCP_CONNECTION_CHECK_TTL ?? 60000), CONNECTION_CHECK_TTL: math(process.env.MCP_CONNECTION_CHECK_TTL ?? 60000),
/** Idle timeout (ms) after which user connections are disconnected. Default: 15 minutes */ /** 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>( const Dialog = React.forwardRef<HTMLDivElement, OGDialogProps>(
({ children, triggerRef, triggerRefs, onOpenChange, ...props }, _ref) => { ({ children, triggerRef, triggerRefs, onOpenChange, ...props }) => {
const handleOpenChange = (open: boolean) => { const handleOpenChange = (open: boolean) => {
if (!open && triggerRef?.current) { if (!open && triggerRef?.current) {
setTimeout(() => { setTimeout(() => {
@ -122,7 +122,6 @@ const DialogContent = React.forwardRef<
{showCloseButton && ( {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"> <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" /> <X className="h-6 w-6" aria-hidden="true" />
{/* eslint-disable-next-line i18next/no-literal-string */}
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
</DialogPrimitive.Close> </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.size).toBe(2); // Only resource1 and resource2 for user
expect(permissionsMap.get(resource1.toString())).toBe(PermissionBits.VIEW); 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 expect(permissionsMap.get(resource3.toString())).toBeUndefined(); // User has no access
}); });
@ -772,7 +774,9 @@ describe('AclEntry Model Tests', () => {
expect(permissionsMap.size).toBe(2); expect(permissionsMap.size).toBe(2);
/** Resource1 should have VIEW | EDIT (from user + group) */ /** 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) */ /** Resource2 should have only VIEW (from user) */
expect(permissionsMap.get(resource2.toString())).toBe(PermissionBits.VIEW); expect(permissionsMap.get(resource2.toString())).toBe(PermissionBits.VIEW);
}); });
@ -847,7 +851,9 @@ describe('AclEntry Model Tests', () => {
); );
expect(permissionsMap.size).toBe(2); 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); expect(permissionsMap.get(resource2.toString())).toBe(PermissionBits.VIEW);
}); });
@ -903,7 +909,9 @@ describe('AclEntry Model Tests', () => {
/** Resources 20-29: USER VIEW | GROUP EDIT */ /** Resources 20-29: USER VIEW | GROUP EDIT */
for (let i = 20; i < 30; i++) { 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 */ /** 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 * Creates or returns the AgentCategory model using the provided mongoose instance and schema
*/ */
export function createAgentCategoryModel(mongoose: typeof import('mongoose')) { 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: { model: {
type: String, type: String,
index: true index: true,
}, },
context: { context: {
type: String, type: String,