feat: Enhance Stream Management with Abort Functionality

- Updated the abort endpoint to support aborting ongoing generation streams using either streamId or conversationId.
- Introduced a new mutation hook `useAbortStreamMutation` for client-side integration.
- Added `useStreamStatus` query to monitor stream status and facilitate resuming conversations.
- Enhanced `useChatHelpers` to incorporate abort functionality when stopping generation.
- Improved `useResumableSSE` to handle stream errors and token refresh seamlessly.
- Updated `useResumeOnLoad` to check for active streams and resume conversations appropriately.
This commit is contained in:
Danny Avila 2025-12-11 21:19:43 -05:00
parent 0a517a2b8f
commit 1985e53b80
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
11 changed files with 295 additions and 136 deletions

View file

@ -0,0 +1,2 @@
export * from './queries';
export * from './mutations';

View file

@ -0,0 +1,39 @@
import { useMutation } from '@tanstack/react-query';
import { request } from 'librechat-data-provider';
export interface AbortStreamParams {
/** The stream ID to abort (if known) */
streamId?: string;
/** The conversation ID to abort (backend will look up the job) */
conversationId?: string;
}
export interface AbortStreamResponse {
success: boolean;
aborted?: string;
error?: string;
}
/**
* Abort an ongoing generation stream.
* The backend will emit a `done` event with `aborted: true` to the SSE stream,
* allowing the client to handle cleanup via the normal event flow.
*
* Can pass either streamId or conversationId - backend will find the job.
*/
export const abortStream = async (params: AbortStreamParams): Promise<AbortStreamResponse> => {
console.log('[abortStream] Calling abort endpoint with params:', params);
const result = (await request.post('/api/agents/chat/abort', params)) as AbortStreamResponse;
console.log('[abortStream] Abort response:', result);
return result;
};
/**
* React Query mutation hook for aborting a generation stream.
* Use this when the user explicitly clicks the stop button.
*/
export function useAbortStreamMutation() {
return useMutation({
mutationFn: abortStream,
});
}

View file

@ -1,5 +1,6 @@
import { useQuery } from '@tanstack/react-query';
import { request } from 'librechat-data-provider';
import type { Agents } from 'librechat-data-provider';
export interface StreamStatusResponse {
active: boolean;
@ -8,6 +9,7 @@ export interface StreamStatusResponse {
chunkCount?: number;
aggregatedContent?: Array<{ type: string; text?: string }>;
createdAt?: number;
resumeState?: Agents.ResumeState;
}
/**
@ -19,8 +21,12 @@ export const streamStatusQueryKey = (conversationId: string) => ['streamStatus',
* Fetch stream status for a conversation
*/
export const fetchStreamStatus = async (conversationId: string): Promise<StreamStatusResponse> => {
const response = await request.get(`/api/agents/chat/status/${conversationId}`);
return response.data;
console.log('[fetchStreamStatus] Fetching status for:', conversationId);
const result = await request.get<StreamStatusResponse>(
`/api/agents/chat/status/${conversationId}`,
);
console.log('[fetchStreamStatus] Result:', result);
return result;
};
/**

View file

@ -15,3 +15,4 @@ export * from './queries';
export * from './roles';
export * from './tags';
export * from './MCP';
export * from './SSE';