Skip to content
Merged
Show file tree
Hide file tree
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
3 changes: 2 additions & 1 deletion client/src/components/Chat/Input/Composer/Queue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { claimQueuedIntent, releaseQueuedIntent, hasQueuedIntent } from '~/utils
import { useQueuedTurnPortal } from '~/components/Chat/Steering/QueuedTurnPortal';
import { escalatingSteerFamily, revealedQueuedTurnFamily } from '~/store/steer';
import EscalateNowButton from '~/components/Chat/Input/EscalateNowButton';
import { queuedMessagesByConvoId } from '~/store/queue';
import { useLocalize } from '~/hooks';
import { cn } from '~/utils';
import store from '~/store';
Expand Down Expand Up @@ -615,7 +616,7 @@ function Queue({
shared constant id would duplicate the element and point every handle's
`aria-describedby` at whichever copy the document happened to keep. */
const reorderHintId = useId();
const queued = useRecoilValue(store.queuedMessagesByConvoId(steering.queueKey));
const queued = useAtomValue(queuedMessagesByConvoId(steering.queueKey));
const pendingSteers = useRecoilValue(store.pendingSteersByConvoId(conversationId));
const escalating = useAtomValue(escalatingSteerFamily(conversationId));
/* Only one interrupt can be unresolved at a time: a second arm would seal the
Expand Down
29 changes: 18 additions & 11 deletions client/src/components/Chat/Input/Composer/__tests__/Queue.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { RecoilRoot } from 'recoil';
import { DndProvider } from 'react-dnd';
import { getDefaultStore } from 'jotai';
import { RecoilRoot, useSetRecoilState } from 'recoil';
import { getDefaultStore, useSetAtom } from 'jotai';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { ReasoningEffort } from 'librechat-data-provider';
import { act, render, screen, within, fireEvent } from '@testing-library/react';
Expand All @@ -11,10 +11,10 @@ import {
QueuedTurnPortalProvider,
useQueuedTurnPortal,
} from '~/components/Chat/Steering/QueuedTurnPortal';
import { queuedMessagesByConvoId, resetQueueFamilies } from '~/store/queue';
import { hasQueuedIntent, releaseQueuedIntent } from '~/utils/queueIntent';
import { revealedQueuedTurnFamily } from '~/store/steer';
import Queue from '../Queue';
import store from '~/store';
jest.mock('~/hooks', () => ({
useLocalize: () => (key: string, options?: Record<string, string | number>) => {
if (!options) {
Expand Down Expand Up @@ -140,7 +140,9 @@ function renderQueue(
} = {},
) {
return render(
<RecoilRoot initializeState={({ set }) => set(store.queuedMessagesByConvoId(CONVO_ID), items)}>
<RecoilRoot
initializeState={() => getDefaultStore().set(queuedMessagesByConvoId(CONVO_ID), items)}
>
{/* Mirrors `App`, which mounts the provider around the whole tree. */}
<DndProvider backend={HTML5Backend}>
<QueuedTurnPortalProvider>
Expand All @@ -161,6 +163,8 @@ function renderQueue(
);
}

beforeEach(() => resetQueueFamilies());

describe('Queue', () => {
beforeEach(() => jest.clearAllMocks());

Expand Down Expand Up @@ -620,8 +624,8 @@ describe('Queue', () => {
render(
<DndProvider backend={HTML5Backend}>
<RecoilRoot
initializeState={({ set }) =>
set(store.queuedMessagesByConvoId(CONVO_ID), [
initializeState={() =>
getDefaultStore().set(queuedMessagesByConvoId(CONVO_ID), [
queued({ id: 'q1' }),
queued({ id: 'q2' }),
])
Expand All @@ -635,8 +639,8 @@ describe('Queue', () => {
/>
</RecoilRoot>
<RecoilRoot
initializeState={({ set }) =>
set(store.queuedMessagesByConvoId(CONVO_ID), [
initializeState={() =>
getDefaultStore().set(queuedMessagesByConvoId(CONVO_ID), [
queued({ id: 'q3' }),
queued({ id: 'q4' }),
])
Expand Down Expand Up @@ -669,13 +673,16 @@ describe('Queue', () => {
it('forgets its last announcement once the queue empties', () => {
let setQueue: (items: QueuedMessage[]) => void = () => undefined;
const Driver = () => {
setQueue = useSetRecoilState(store.queuedMessagesByConvoId(CONVO_ID));
setQueue = useSetAtom(queuedMessagesByConvoId(CONVO_ID));
return null;
};
render(
<RecoilRoot
initializeState={({ set }) =>
set(store.queuedMessagesByConvoId(CONVO_ID), [queued({ id: 'q1' }), queued({ id: 'q2' })])
initializeState={() =>
getDefaultStore().set(queuedMessagesByConvoId(CONVO_ID), [
queued({ id: 'q1' }),
queued({ id: 'q2' }),
])
}
>
<Driver />
Expand Down
12 changes: 8 additions & 4 deletions client/src/hooks/Chat/__tests__/abort.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';
import { Constants } from 'librechat-data-provider';
import { useAtomValue, useSetAtom, getDefaultStore } from 'jotai';
import { act, renderHook, waitFor } from '@testing-library/react';
import { RecoilRoot, useSetRecoilState, useRecoilValue } from 'recoil';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { TSubmission, TConversation } from 'librechat-data-provider';
import type { DrainAfterAbort, RunEnd } from '~/store/families';
import { drainAfterAbortByIndex, runEndByIndex, resetQueueFamilies } from '~/store/queue';
import useChatHelpers from '../useChatHelpers';
import { useAbortCleanup } from '../abort';
import store from '~/store';
Expand Down Expand Up @@ -87,6 +89,8 @@ function setup() {
return { handles, current };
}

beforeEach(() => resetQueueFamilies());

describe('useAbortCleanup', () => {
it('clears all submissions when the captured submission is still current', async () => {
const { handles, current } = setup();
Expand Down Expand Up @@ -180,9 +184,9 @@ describe('useChatHelpers stopGenerating (abort steer targeting)', () => {
function setupStop(conversationId: string, generationCreatedAt: number | null = 41) {
let setDrainAfterAbort: ((value: DrainAfterAbort | false) => void) | undefined;
function RunEndProbe() {
observed.runEnd = useRecoilValue(store.runEndByIndex(INDEX));
observed.drainAfterAbort = useRecoilValue(store.drainAfterAbortByIndex(INDEX));
setDrainAfterAbort = useSetRecoilState(store.drainAfterAbortByIndex(INDEX));
observed.runEnd = useAtomValue(runEndByIndex(INDEX));
observed.drainAfterAbort = useAtomValue(drainAfterAbortByIndex(INDEX));
setDrainAfterAbort = useSetAtom(drainAfterAbortByIndex(INDEX));
return null;
}
const queryClient = new QueryClient();
Expand All @@ -195,7 +199,7 @@ describe('useChatHelpers stopGenerating (abort steer targeting)', () => {
endpoint: 'agents',
} as TConversation);
// Arm interrupt & send so the abort response writes the drain signal.
set(store.drainAfterAbortByIndex(INDEX), {
getDefaultStore().set(drainAfterAbortByIndex(INDEX), {
conversationId,
generationCreatedAt: 41,
});
Expand Down
6 changes: 5 additions & 1 deletion client/src/hooks/Chat/__tests__/transport.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { useAtomValue } from 'jotai';
import { MemoryRouter } from 'react-router-dom';
import { RecoilRoot, useRecoilValue } from 'recoil';
import { QueryKeys } from 'librechat-data-provider';
Expand All @@ -14,6 +15,7 @@ import type {
import type { MutableSnapshot } from 'recoil';
import type { Transport } from '~/hooks/Chat/contract';
import type { PendingSteer } from '~/store/families';
import { queuedMessagesByConvoId, resetQueueFamilies } from '~/store/queue';
import { ChatTransportContext } from '~/Providers/ChatTransportContext';
import { useSteerReclaim } from '~/hooks/Chat/useSteerCancel';
import useSteerEscalate from '~/hooks/Chat/useSteerEscalate';
Expand Down Expand Up @@ -172,11 +174,13 @@ const renderSteering = (transport: Transport) =>
sendNow: jest.fn(),
stopGenerating: jest.fn(),
}),
queue: useRecoilValue(store.queuedMessagesByConvoId('convo-1')),
queue: useAtomValue(queuedMessagesByConvoId('convo-1')),
}),
{ wrapper: createWrapper(transport, seedSteerableRun, seedLiveBranch) },
);

beforeEach(() => resetQueueFamilies());

describe('chat transport boundary', () => {
describe('send (agents)', () => {
it('starts the turn and attaches to its stream through the host transport', async () => {
Expand Down
Loading
Loading