| | import { |
| | Constants, |
| | defaultAssistantsVersion, |
| | ConversationListResponse, |
| | } from 'librechat-data-provider'; |
| | import { useMutation, useQueryClient } from '@tanstack/react-query'; |
| | import { dataService, MutationKeys, QueryKeys, defaultOrderQuery } from 'librechat-data-provider'; |
| | import type { InfiniteData, UseMutationResult } from '@tanstack/react-query'; |
| | import type * as t from 'librechat-data-provider'; |
| | import { |
| | logger, |
| | |
| | addConvoToAllQueries, |
| | updateConvoInAllQueries, |
| | removeConvoFromAllQueries, |
| | } from '~/utils'; |
| | import useUpdateTagsInConvo from '~/hooks/Conversations/useUpdateTagsInConvo'; |
| | import { updateConversationTag } from '~/utils/conversationTags'; |
| | import { useConversationTagsQuery } from './queries'; |
| |
|
| | export type TGenTitleMutation = UseMutationResult< |
| | t.TGenTitleResponse, |
| | unknown, |
| | t.TGenTitleRequest, |
| | unknown |
| | >; |
| |
|
| | export const useGenTitleMutation = (): TGenTitleMutation => { |
| | const queryClient = useQueryClient(); |
| | return useMutation((payload: t.TGenTitleRequest) => dataService.genTitle(payload), { |
| | onSuccess: (response, vars) => { |
| | queryClient.setQueryData( |
| | [QueryKeys.conversation, vars.conversationId], |
| | (convo: t.TConversation | undefined) => |
| | convo ? { ...convo, title: response.title } : convo, |
| | ); |
| | updateConvoInAllQueries(queryClient, vars.conversationId, (c) => ({ |
| | ...c, |
| | title: response.title, |
| | })); |
| | document.title = response.title; |
| | }, |
| | }); |
| | }; |
| |
|
| | export const useUpdateConversationMutation = ( |
| | id: string, |
| | ): UseMutationResult< |
| | t.TUpdateConversationResponse, |
| | unknown, |
| | t.TUpdateConversationRequest, |
| | unknown |
| | > => { |
| | const queryClient = useQueryClient(); |
| | return useMutation( |
| | (payload: t.TUpdateConversationRequest) => dataService.updateConversation(payload), |
| | { |
| | onSuccess: (updatedConvo, payload) => { |
| | const targetId = payload.conversationId || id; |
| | queryClient.setQueryData([QueryKeys.conversation, targetId], updatedConvo); |
| | updateConvoInAllQueries(queryClient, targetId, () => updatedConvo); |
| | }, |
| | }, |
| | ); |
| | }; |
| |
|
| | export const useTagConversationMutation = ( |
| | conversationId: string, |
| | options?: t.updateTagsInConvoOptions, |
| | ): UseMutationResult<t.TTagConversationResponse, unknown, t.TTagConversationRequest, unknown> => { |
| | const query = useConversationTagsQuery(); |
| | const { updateTagsInConversation } = useUpdateTagsInConvo(); |
| | return useMutation( |
| | (payload: t.TTagConversationRequest) => |
| | dataService.addTagToConversation(conversationId, payload), |
| | { |
| | onSuccess: (updatedTags, ...rest) => { |
| | query.refetch(); |
| | updateTagsInConversation(conversationId, updatedTags); |
| | options?.onSuccess?.(updatedTags, ...rest); |
| | }, |
| | onError: options?.onError, |
| | onMutate: options?.onMutate, |
| | }, |
| | ); |
| | }; |
| |
|
| | export const useArchiveConvoMutation = ( |
| | options?: t.ArchiveConversationOptions, |
| | ): UseMutationResult< |
| | t.TArchiveConversationResponse, |
| | unknown, |
| | t.TArchiveConversationRequest, |
| | unknown |
| | > => { |
| | const queryClient = useQueryClient(); |
| | const convoQueryKey = [QueryKeys.allConversations]; |
| | const archivedConvoQueryKey = [QueryKeys.archivedConversations]; |
| | const { onMutate, onError, onSuccess, ..._options } = options || {}; |
| |
|
| | return useMutation( |
| | (payload: t.TArchiveConversationRequest) => dataService.archiveConversation(payload), |
| | { |
| | onMutate, |
| | onSuccess: (_data, vars, context) => { |
| | const isArchived = vars.isArchived === true; |
| |
|
| | removeConvoFromAllQueries(queryClient, vars.conversationId); |
| |
|
| | const archivedQueries = queryClient |
| | .getQueryCache() |
| | .findAll([QueryKeys.archivedConversations], { exact: false }); |
| |
|
| | for (const query of archivedQueries) { |
| | queryClient.setQueryData<InfiniteData<ConversationListResponse>>( |
| | query.queryKey, |
| | (oldData) => { |
| | if (!oldData) { |
| | return oldData; |
| | } |
| | if (isArchived) { |
| | return { |
| | ...oldData, |
| | pages: [ |
| | { |
| | ...oldData.pages[0], |
| | conversations: [_data, ...oldData.pages[0].conversations], |
| | }, |
| | ...oldData.pages.slice(1), |
| | ], |
| | }; |
| | } else { |
| | return { |
| | ...oldData, |
| | pages: oldData.pages.map((page) => ({ |
| | ...page, |
| | conversations: page.conversations.filter( |
| | (conv) => conv.conversationId !== vars.conversationId, |
| | ), |
| | })), |
| | }; |
| | } |
| | }, |
| | ); |
| | } |
| |
|
| | queryClient.setQueryData( |
| | [QueryKeys.conversation, vars.conversationId], |
| | isArchived ? null : _data, |
| | ); |
| |
|
| | onSuccess?.(_data, vars, context); |
| | }, |
| | onError, |
| | onSettled: () => { |
| | queryClient.invalidateQueries({ |
| | queryKey: convoQueryKey, |
| | refetchPage: (_, index) => index === 0, |
| | }); |
| | queryClient.invalidateQueries({ |
| | queryKey: archivedConvoQueryKey, |
| | refetchPage: (_, index) => index === 0, |
| | }); |
| | }, |
| | ..._options, |
| | }, |
| | ); |
| | }; |
| |
|
| | export const useCreateSharedLinkMutation = ( |
| | options?: t.MutationOptions< |
| | t.TCreateShareLinkRequest, |
| | { conversationId: string; targetMessageId?: string } |
| | >, |
| | ): UseMutationResult< |
| | t.TSharedLinkResponse, |
| | unknown, |
| | { conversationId: string; targetMessageId?: string }, |
| | unknown |
| | > => { |
| | const queryClient = useQueryClient(); |
| |
|
| | const { onSuccess, ..._options } = options || {}; |
| | return useMutation( |
| | ({ conversationId, targetMessageId }: { conversationId: string; targetMessageId?: string }) => { |
| | if (!conversationId) { |
| | throw new Error('Conversation ID is required'); |
| | } |
| |
|
| | return dataService.createSharedLink(conversationId, targetMessageId); |
| | }, |
| | { |
| | onSuccess: (_data: t.TSharedLinkResponse, vars, context) => { |
| | queryClient.setQueryData([QueryKeys.sharedLinks, _data.conversationId], _data); |
| |
|
| | onSuccess?.(_data, vars, context); |
| | }, |
| | ..._options, |
| | }, |
| | ); |
| | }; |
| |
|
| | export const useUpdateSharedLinkMutation = ( |
| | options?: t.MutationOptions<t.TUpdateShareLinkRequest, { shareId: string }>, |
| | ): UseMutationResult<t.TSharedLinkResponse, unknown, { shareId: string }, unknown> => { |
| | const queryClient = useQueryClient(); |
| |
|
| | const { onSuccess, ..._options } = options || {}; |
| | return useMutation( |
| | ({ shareId }) => { |
| | if (!shareId) { |
| | throw new Error('Share ID is required'); |
| | } |
| | return dataService.updateSharedLink(shareId); |
| | }, |
| | { |
| | onSuccess: (_data: t.TSharedLinkResponse, vars, context) => { |
| | queryClient.setQueryData([QueryKeys.sharedLinks, _data.conversationId], _data); |
| |
|
| | onSuccess?.(_data, vars, context); |
| | }, |
| | ..._options, |
| | }, |
| | ); |
| | }; |
| |
|
| | export const useDeleteSharedLinkMutation = ( |
| | options?: t.DeleteSharedLinkOptions, |
| | ): UseMutationResult< |
| | t.TDeleteSharedLinkResponse, |
| | unknown, |
| | { shareId: string }, |
| | t.DeleteSharedLinkContext |
| | > => { |
| | const queryClient = useQueryClient(); |
| | const { onSuccess } = options || {}; |
| |
|
| | return useMutation((vars) => dataService.deleteSharedLink(vars.shareId), { |
| | onMutate: async (vars) => { |
| | await queryClient.cancelQueries({ |
| | queryKey: [QueryKeys.sharedLinks], |
| | exact: false, |
| | }); |
| |
|
| | const previousQueries = new Map(); |
| | const queryKeys = queryClient.getQueryCache().findAll([QueryKeys.sharedLinks]); |
| |
|
| | queryKeys.forEach((query) => { |
| | const previousData = queryClient.getQueryData(query.queryKey); |
| | previousQueries.set(query.queryKey, previousData); |
| |
|
| | queryClient.setQueryData<t.SharedLinkQueryData>(query.queryKey, (old) => { |
| | if (!old?.pages) { |
| | return old; |
| | } |
| |
|
| | const updatedPages = old.pages.map((page) => ({ |
| | ...page, |
| | links: page.links.filter((link) => link.shareId !== vars.shareId), |
| | })); |
| |
|
| | const nonEmptyPages = updatedPages.filter((page) => page.links.length > 0); |
| |
|
| | return { |
| | ...old, |
| | pages: nonEmptyPages, |
| | }; |
| | }); |
| | }); |
| |
|
| | return { previousQueries }; |
| | }, |
| |
|
| | onError: (_err, _vars, context) => { |
| | if (context?.previousQueries) { |
| | context.previousQueries.forEach((prevData: unknown, prevQueryKey: unknown) => { |
| | queryClient.setQueryData(prevQueryKey as string[], prevData); |
| | }); |
| | } |
| | }, |
| |
|
| | onSettled: () => { |
| | queryClient.invalidateQueries({ |
| | queryKey: [QueryKeys.sharedLinks], |
| | exact: false, |
| | }); |
| | }, |
| |
|
| | onSuccess: (data, variables) => { |
| | if (onSuccess) { |
| | onSuccess(data, variables); |
| | } |
| |
|
| | queryClient.refetchQueries({ |
| | queryKey: [QueryKeys.sharedLinks], |
| | exact: true, |
| | }); |
| | }, |
| | }); |
| | }; |
| |
|
| | |
| | export const useConversationTagMutation = ({ |
| | context, |
| | tag, |
| | options, |
| | }: { |
| | context: string; |
| | tag?: string; |
| | options?: t.UpdateConversationTagOptions; |
| | }): UseMutationResult<t.TConversationTagResponse, unknown, t.TConversationTagRequest, unknown> => { |
| | const queryClient = useQueryClient(); |
| | const { onSuccess, ..._options } = options || {}; |
| | const onMutationSuccess: typeof onSuccess = (_data, vars) => { |
| | queryClient.setQueryData<t.TConversationTag[]>([QueryKeys.conversationTags], (queryData) => { |
| | if (!queryData) { |
| | return [ |
| | { |
| | count: 1, |
| | position: 0, |
| | tag: Constants.SAVED_TAG, |
| | createdAt: new Date().toISOString(), |
| | updatedAt: new Date().toISOString(), |
| | }, |
| | ] as t.TConversationTag[]; |
| | } |
| | if (tag === undefined || !tag.length) { |
| | |
| | const existingTagIndex = queryData.findIndex((item) => item.tag === _data.tag); |
| | if (existingTagIndex !== -1) { |
| | logger.log( |
| | 'tag_mutation', |
| | `"Created" tag exists, updating from ${context}`, |
| | queryData, |
| | _data, |
| | ); |
| | |
| | const updatedData = [...queryData]; |
| | updatedData[existingTagIndex] = { ...updatedData[existingTagIndex], ..._data }; |
| | return updatedData.sort((a, b) => a.position - b.position); |
| | } else { |
| | |
| | logger.log( |
| | 'tag_mutation', |
| | `"Created" tag is new, adding from ${context}`, |
| | queryData, |
| | _data, |
| | ); |
| | return [...queryData, _data].sort((a, b) => a.position - b.position); |
| | } |
| | } |
| | logger.log('tag_mutation', `Updating tag from ${context}`, queryData, _data); |
| | return updateConversationTag(queryData, vars, _data, tag); |
| | }); |
| | if (vars.addToConversation === true && vars.conversationId != null && _data.tag) { |
| | const currentConvo = queryClient.getQueryData<t.TConversation>([ |
| | QueryKeys.conversation, |
| | vars.conversationId, |
| | ]); |
| | if (!currentConvo) { |
| | return; |
| | } |
| | logger.log( |
| | 'tag_mutation', |
| | `\`updateTagsInConversation\` Update from ${context}`, |
| | currentConvo, |
| | ); |
| | updateTagsInConversation(vars.conversationId, [...(currentConvo.tags || []), _data.tag]); |
| | } |
| | |
| | if (tag != null) { |
| | replaceTagsInAllConversations(tag, _data.tag); |
| | } |
| | }; |
| | const { updateTagsInConversation, replaceTagsInAllConversations } = useUpdateTagsInConvo(); |
| | return useMutation( |
| | (payload: t.TConversationTagRequest) => |
| | tag != null |
| | ? dataService.updateConversationTag(tag, payload) |
| | : dataService.createConversationTag(payload), |
| | { |
| | onSuccess: (...args) => { |
| | onMutationSuccess(...args); |
| | onSuccess?.(...args); |
| | }, |
| | ..._options, |
| | }, |
| | ); |
| | }; |
| |
|
| | |
| | export const useDeleteTagInConversations = () => { |
| | const queryClient = useQueryClient(); |
| | const deleteTagInAllConversation = (deletedTag: string) => { |
| | const data = queryClient.getQueryData<InfiniteData<ConversationListResponse>>([ |
| | QueryKeys.allConversations, |
| | ]); |
| |
|
| | |
| | if (!data || !Array.isArray(data.pages) || data.pages.length === 0) { |
| | return; |
| | } |
| |
|
| | const conversationIdsWithTag: string[] = []; |
| |
|
| | |
| | const updatedData: InfiniteData<ConversationListResponse> = { |
| | pageParams: Array.isArray(data.pageParams) ? [...data.pageParams] : [], |
| | pages: data.pages.map((page) => ({ |
| | ...page, |
| | conversations: page.conversations.map((conversation) => { |
| | if ( |
| | conversation.conversationId && |
| | 'tags' in conversation && |
| | Array.isArray((conversation as unknown as { tags?: string[] }).tags) && |
| | (conversation as unknown as { tags: string[] }).tags.includes(deletedTag) |
| | ) { |
| | conversationIdsWithTag.push(conversation.conversationId); |
| | return { |
| | ...conversation, |
| | tags: (conversation as unknown as { tags: string[] }).tags.filter( |
| | (tag: string) => tag !== deletedTag, |
| | ), |
| | } as t.TConversation; |
| | } |
| | return conversation as t.TConversation; |
| | }), |
| | })), |
| | }; |
| |
|
| | queryClient.setQueryData<InfiniteData<ConversationListResponse>>( |
| | [QueryKeys.allConversations], |
| | updatedData, |
| | ); |
| |
|
| | |
| | for (let i = 0; i < conversationIdsWithTag.length; i++) { |
| | const conversationId = conversationIdsWithTag[i]; |
| | const conversationData = queryClient.getQueryData<t.TConversation>([ |
| | QueryKeys.conversation, |
| | conversationId, |
| | ]); |
| | if (conversationData && Array.isArray((conversationData as { tags?: string[] }).tags)) { |
| | queryClient.setQueryData<t.TConversation>([QueryKeys.conversation, conversationId], { |
| | ...conversationData, |
| | tags: (conversationData as { tags: string[] }).tags.filter( |
| | (tag: string) => tag !== deletedTag, |
| | ), |
| | }); |
| | } |
| | } |
| | }; |
| | return deleteTagInAllConversation; |
| | }; |
| |
|
| | export const useDeleteConversationTagMutation = ( |
| | options?: t.DeleteConversationTagOptions, |
| | ): UseMutationResult<t.TConversationTagResponse, unknown, string, void> => { |
| | const queryClient = useQueryClient(); |
| | const deleteTagInAllConversations = useDeleteTagInConversations(); |
| |
|
| | const { onSuccess, ..._options } = options || {}; |
| |
|
| | return useMutation((tag: string) => dataService.deleteConversationTag(tag), { |
| | onSuccess: (_data, tagToDelete, context) => { |
| | queryClient.setQueryData<t.TConversationTag[]>([QueryKeys.conversationTags], (data) => { |
| | if (!data) { |
| | return data; |
| | } |
| | return data.filter((t) => t.tag !== tagToDelete); |
| | }); |
| |
|
| | deleteTagInAllConversations(tagToDelete); |
| | onSuccess?.(_data, tagToDelete, context); |
| | }, |
| | ..._options, |
| | }); |
| | }; |
| |
|
| | export const useDeleteConversationMutation = ( |
| | options?: t.DeleteConversationOptions, |
| | ): UseMutationResult< |
| | t.TDeleteConversationResponse, |
| | unknown, |
| | t.TDeleteConversationRequest, |
| | unknown |
| | > => { |
| | const queryClient = useQueryClient(); |
| |
|
| | return useMutation( |
| | (payload: t.TDeleteConversationRequest) => |
| | dataService.deleteConversation(payload) as Promise<t.TDeleteConversationResponse>, |
| | { |
| | onMutate: async () => { |
| | await queryClient.cancelQueries([QueryKeys.allConversations]); |
| | await queryClient.cancelQueries([QueryKeys.archivedConversations]); |
| | |
| | }, |
| | onError: () => { |
| | |
| | }, |
| | onSuccess: (data, vars, context) => { |
| | if (vars.conversationId) { |
| | removeConvoFromAllQueries(queryClient, vars.conversationId); |
| | } |
| |
|
| | |
| | const archivedQueries = queryClient |
| | .getQueryCache() |
| | .findAll([QueryKeys.archivedConversations], { exact: false }); |
| |
|
| | for (const query of archivedQueries) { |
| | queryClient.setQueryData<InfiniteData<ConversationListResponse>>( |
| | query.queryKey, |
| | (oldData) => { |
| | if (!oldData) { |
| | return oldData; |
| | } |
| | return { |
| | ...oldData, |
| | pages: oldData.pages |
| | .map((page) => ({ |
| | ...page, |
| | conversations: page.conversations.filter( |
| | (conv) => conv.conversationId !== vars.conversationId, |
| | ), |
| | })) |
| | .filter((page) => page.conversations.length > 0), |
| | }; |
| | }, |
| | ); |
| | } |
| |
|
| | queryClient.removeQueries({ |
| | queryKey: [QueryKeys.conversation, vars.conversationId], |
| | exact: true, |
| | }); |
| |
|
| | queryClient.invalidateQueries({ |
| | queryKey: [QueryKeys.allConversations], |
| | refetchPage: (_, index) => index === 0, |
| | }); |
| | queryClient.invalidateQueries({ |
| | queryKey: [QueryKeys.archivedConversations], |
| | refetchPage: (_, index) => index === 0, |
| | }); |
| |
|
| | options?.onSuccess?.(data, vars, context); |
| | }, |
| | }, |
| | ); |
| | }; |
| |
|
| | export const useDuplicateConversationMutation = ( |
| | options?: t.DuplicateConvoOptions, |
| | ): UseMutationResult<t.TDuplicateConvoResponse, unknown, t.TDuplicateConvoRequest, unknown> => { |
| | const queryClient = useQueryClient(); |
| | const { onSuccess, ..._options } = options ?? {}; |
| | return useMutation((payload) => dataService.duplicateConversation(payload), { |
| | onSuccess: (data, vars, context) => { |
| | const duplicatedConversation = data.conversation; |
| | if (!duplicatedConversation?.conversationId) { |
| | return; |
| | } |
| | queryClient.setQueryData( |
| | [QueryKeys.conversation, duplicatedConversation.conversationId], |
| | duplicatedConversation, |
| | ); |
| | addConvoToAllQueries(queryClient, duplicatedConversation); |
| | queryClient.setQueryData( |
| | [QueryKeys.messages, duplicatedConversation.conversationId], |
| | data.messages, |
| | ); |
| | queryClient.invalidateQueries({ |
| | queryKey: [QueryKeys.allConversations], |
| | refetchPage: (_, index) => index === 0, |
| | }); |
| |
|
| | if (duplicatedConversation.tags && duplicatedConversation.tags.length > 0) { |
| | queryClient.setQueryData<t.TConversationTag[]>([QueryKeys.conversationTags], (oldTags) => { |
| | if (!oldTags) return oldTags; |
| | return oldTags.map((tag) => { |
| | if (duplicatedConversation.tags?.includes(tag.tag)) { |
| | return { ...tag, count: tag.count + 1 }; |
| | } |
| | return tag; |
| | }); |
| | }); |
| | } |
| |
|
| | onSuccess?.(data, vars, context); |
| | }, |
| | ..._options, |
| | }); |
| | }; |
| |
|
| | export const useForkConvoMutation = ( |
| | options?: t.ForkConvoOptions, |
| | ): UseMutationResult<t.TForkConvoResponse, unknown, t.TForkConvoRequest, unknown> => { |
| | const queryClient = useQueryClient(); |
| | const { onSuccess, ..._options } = options || {}; |
| |
|
| | return useMutation((payload: t.TForkConvoRequest) => dataService.forkConversation(payload), { |
| | onSuccess: (data, vars, context) => { |
| | if (!vars.conversationId) { |
| | return; |
| | } |
| | const forkedConversation = data.conversation; |
| | const forkedConversationId = forkedConversation.conversationId; |
| | if (!forkedConversationId) { |
| | return; |
| | } |
| |
|
| | queryClient.setQueryData([QueryKeys.conversation, forkedConversationId], forkedConversation); |
| | addConvoToAllQueries(queryClient, forkedConversation); |
| | queryClient.setQueryData([QueryKeys.messages, forkedConversationId], data.messages); |
| | queryClient.invalidateQueries({ |
| | queryKey: [QueryKeys.allConversations], |
| | refetchPage: (_, index) => index === 0, |
| | }); |
| |
|
| | if (forkedConversation.tags && forkedConversation.tags.length > 0) { |
| | queryClient.setQueryData<t.TConversationTag[]>([QueryKeys.conversationTags], (oldTags) => { |
| | if (!oldTags) return oldTags; |
| | return oldTags.map((tag) => { |
| | if (forkedConversation.tags?.includes(tag.tag)) { |
| | return { ...tag, count: tag.count + 1 }; |
| | } |
| | return tag; |
| | }); |
| | }); |
| | } |
| |
|
| | onSuccess?.(data, vars, context); |
| | }, |
| | ..._options, |
| | }); |
| | }; |
| |
|
| | export const useUploadConversationsMutation = ( |
| | _options?: t.MutationOptions<t.TImportResponse, FormData>, |
| | ) => { |
| | const queryClient = useQueryClient(); |
| | const { onSuccess, onError, onMutate } = _options || {}; |
| |
|
| | return useMutation<t.TImportResponse, unknown, FormData>({ |
| | mutationFn: (formData: FormData) => dataService.importConversationsFile(formData), |
| | onSuccess: (data, variables, context) => { |
| | |
| | queryClient.invalidateQueries([QueryKeys.allConversations]); |
| | if (onSuccess) { |
| | onSuccess(data, variables, context); |
| | } |
| | }, |
| | onError: (err, variables, context) => { |
| | if (onError) { |
| | onError(err, variables, context); |
| | } |
| | }, |
| | onMutate, |
| | }); |
| | }; |
| |
|
| | export const useUpdatePresetMutation = ( |
| | options?: t.UpdatePresetOptions, |
| | ): UseMutationResult< |
| | t.TPreset, |
| | unknown, |
| | t.TPreset, |
| | unknown |
| | > => { |
| | return useMutation([MutationKeys.updatePreset], { |
| | mutationFn: (preset: t.TPreset) => dataService.updatePreset(preset), |
| | ...(options || {}), |
| | }); |
| | }; |
| |
|
| | export const useDeletePresetMutation = ( |
| | options?: t.DeletePresetOptions, |
| | ): UseMutationResult< |
| | t.PresetDeleteResponse, |
| | unknown, |
| | t.TPreset | undefined, |
| | unknown |
| | > => { |
| | return useMutation([MutationKeys.deletePreset], { |
| | mutationFn: (preset: t.TPreset | undefined) => dataService.deletePreset(preset), |
| | ...(options || {}), |
| | }); |
| | }; |
| |
|
| | |
| | export const useUploadAvatarMutation = ( |
| | options?: t.UploadAvatarOptions, |
| | ): UseMutationResult< |
| | t.AvatarUploadResponse, |
| | unknown, |
| | FormData, |
| | unknown |
| | > => { |
| | return useMutation([MutationKeys.avatarUpload], { |
| | mutationFn: (variables: FormData) => dataService.uploadAvatar(variables), |
| | ...(options || {}), |
| | }); |
| | }; |
| |
|
| | |
| | export const useSpeechToTextMutation = ( |
| | options?: t.SpeechToTextOptions, |
| | ): UseMutationResult< |
| | t.SpeechToTextResponse, |
| | unknown, |
| | FormData, |
| | unknown |
| | > => { |
| | return useMutation([MutationKeys.speechToText], { |
| | mutationFn: (variables: FormData) => dataService.speechToText(variables), |
| | ...(options || {}), |
| | }); |
| | }; |
| |
|
| | |
| | export const useTextToSpeechMutation = ( |
| | options?: t.TextToSpeechOptions, |
| | ): UseMutationResult< |
| | ArrayBuffer, |
| | unknown, |
| | FormData, |
| | unknown |
| | > => { |
| | return useMutation([MutationKeys.textToSpeech], { |
| | mutationFn: (variables: FormData) => dataService.textToSpeech(variables), |
| | ...(options || {}), |
| | }); |
| | }; |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | export const useCreateAssistantMutation = ( |
| | options?: t.CreateAssistantMutationOptions, |
| | ): UseMutationResult<t.Assistant, Error, t.AssistantCreateParams> => { |
| | const queryClient = useQueryClient(); |
| | return useMutation( |
| | (newAssistantData: t.AssistantCreateParams) => dataService.createAssistant(newAssistantData), |
| | { |
| | onMutate: (variables) => options?.onMutate?.(variables), |
| | onError: (error, variables, context) => options?.onError?.(error, variables, context), |
| | onSuccess: (newAssistant, variables, context) => { |
| | const listRes = queryClient.getQueryData<t.AssistantListResponse>([ |
| | QueryKeys.assistants, |
| | variables.endpoint, |
| | defaultOrderQuery, |
| | ]); |
| |
|
| | if (!listRes) { |
| | return options?.onSuccess?.(newAssistant, variables, context); |
| | } |
| |
|
| | const currentAssistants = [newAssistant, ...JSON.parse(JSON.stringify(listRes.data))]; |
| |
|
| | queryClient.setQueryData<t.AssistantListResponse>( |
| | [QueryKeys.assistants, variables.endpoint, defaultOrderQuery], |
| | { |
| | ...listRes, |
| | data: currentAssistants, |
| | }, |
| | ); |
| | return options?.onSuccess?.(newAssistant, variables, context); |
| | }, |
| | }, |
| | ); |
| | }; |
| |
|
| | |
| | |
| | |
| | export const useUpdateAssistantMutation = ( |
| | options?: t.UpdateAssistantMutationOptions, |
| | ): UseMutationResult< |
| | t.Assistant, |
| | Error, |
| | { assistant_id: string; data: t.AssistantUpdateParams } |
| | > => { |
| | const queryClient = useQueryClient(); |
| | return useMutation( |
| | ({ assistant_id, data }: { assistant_id: string; data: t.AssistantUpdateParams }) => { |
| | const { endpoint } = data; |
| | const endpointsConfig = queryClient.getQueryData<t.TEndpointsConfig>([QueryKeys.endpoints]); |
| | const endpointConfig = endpointsConfig?.[endpoint]; |
| | const version = endpointConfig?.version ?? defaultAssistantsVersion[endpoint]; |
| | return dataService.updateAssistant({ |
| | data, |
| | version, |
| | assistant_id, |
| | }); |
| | }, |
| | { |
| | onMutate: (variables) => options?.onMutate?.(variables), |
| | onError: (error, variables, context) => options?.onError?.(error, variables, context), |
| | onSuccess: (updatedAssistant, variables, context) => { |
| | const listRes = queryClient.getQueryData<t.AssistantListResponse>([ |
| | QueryKeys.assistants, |
| | variables.data.endpoint, |
| | defaultOrderQuery, |
| | ]); |
| |
|
| | if (!listRes) { |
| | return options?.onSuccess?.(updatedAssistant, variables, context); |
| | } |
| |
|
| | queryClient.setQueryData<t.AssistantDocument[]>( |
| | [QueryKeys.assistantDocs, variables.data.endpoint], |
| | (prev) => { |
| | if (!prev) { |
| | return prev; |
| | } |
| | return prev.map((doc) => { |
| | if (doc.assistant_id === variables.assistant_id) { |
| | return { |
| | ...doc, |
| | conversation_starters: updatedAssistant.conversation_starters, |
| | append_current_datetime: variables.data.append_current_datetime, |
| | }; |
| | } |
| | return doc; |
| | }); |
| | }, |
| | ); |
| |
|
| | queryClient.setQueryData<t.AssistantListResponse>( |
| | [QueryKeys.assistants, variables.data.endpoint, defaultOrderQuery], |
| | { |
| | ...listRes, |
| | data: listRes.data.map((assistant) => { |
| | if (assistant.id === variables.assistant_id) { |
| | return updatedAssistant; |
| | } |
| | return assistant; |
| | }), |
| | }, |
| | ); |
| | return options?.onSuccess?.(updatedAssistant, variables, context); |
| | }, |
| | }, |
| | ); |
| | }; |
| |
|
| | |
| | |
| | |
| | export const useDeleteAssistantMutation = ( |
| | options?: t.DeleteAssistantMutationOptions, |
| | ): UseMutationResult<void, Error, t.DeleteAssistantBody> => { |
| | const queryClient = useQueryClient(); |
| | return useMutation( |
| | ({ assistant_id, model, endpoint }: t.DeleteAssistantBody) => { |
| | const endpointsConfig = queryClient.getQueryData<t.TEndpointsConfig>([QueryKeys.endpoints]); |
| | const version = endpointsConfig?.[endpoint]?.version ?? defaultAssistantsVersion[endpoint]; |
| | return dataService.deleteAssistant({ assistant_id, model, version, endpoint }); |
| | }, |
| | { |
| | onMutate: (variables) => options?.onMutate?.(variables), |
| | onError: (error, variables, context) => options?.onError?.(error, variables, context), |
| | onSuccess: (_data, variables, context) => { |
| | const listRes = queryClient.getQueryData<t.AssistantListResponse>([ |
| | QueryKeys.assistants, |
| | variables.endpoint, |
| | defaultOrderQuery, |
| | ]); |
| |
|
| | if (!listRes) { |
| | return options?.onSuccess?.(_data, variables, context); |
| | } |
| |
|
| | const data = listRes.data.filter((assistant) => assistant.id !== variables.assistant_id); |
| |
|
| | queryClient.setQueryData<t.AssistantListResponse>( |
| | [QueryKeys.assistants, variables.endpoint, defaultOrderQuery], |
| | { |
| | ...listRes, |
| | data, |
| | }, |
| | ); |
| |
|
| | return options?.onSuccess?.(_data, variables, data); |
| | }, |
| | }, |
| | ); |
| | }; |
| |
|
| | |
| | |
| | |
| | export const useUploadAssistantAvatarMutation = ( |
| | options?: t.UploadAssistantAvatarOptions, |
| | ): UseMutationResult< |
| | t.Assistant, |
| | unknown, |
| | t.AssistantAvatarVariables, |
| | unknown |
| | > => { |
| | return useMutation([MutationKeys.assistantAvatarUpload], { |
| | mutationFn: ({ postCreation: _postCreation, ...variables }: t.AssistantAvatarVariables) => |
| | dataService.uploadAssistantAvatar(variables), |
| | ...(options || {}), |
| | }); |
| | }; |
| |
|
| | |
| | |
| | |
| | export const useUpdateAction = ( |
| | options?: t.UpdateActionOptions, |
| | ): UseMutationResult< |
| | t.UpdateActionResponse, |
| | unknown, |
| | t.UpdateActionVariables, |
| | unknown |
| | > => { |
| | const queryClient = useQueryClient(); |
| | return useMutation([MutationKeys.updateAction], { |
| | mutationFn: (variables: t.UpdateActionVariables) => dataService.updateAction(variables), |
| |
|
| | onMutate: (variables) => options?.onMutate?.(variables), |
| | onError: (error, variables, context) => options?.onError?.(error, variables, context), |
| | onSuccess: (updateActionResponse, variables, context) => { |
| | const listRes = queryClient.getQueryData<t.AssistantListResponse>([ |
| | QueryKeys.assistants, |
| | variables.endpoint, |
| | defaultOrderQuery, |
| | ]); |
| |
|
| | if (!listRes) { |
| | return options?.onSuccess?.(updateActionResponse, variables, context); |
| | } |
| |
|
| | const updatedAssistant = updateActionResponse[1]; |
| |
|
| | queryClient.setQueryData<t.AssistantListResponse>( |
| | [QueryKeys.assistants, variables.endpoint, defaultOrderQuery], |
| | { |
| | ...listRes, |
| | data: listRes.data.map((assistant) => { |
| | if (assistant.id === variables.assistant_id) { |
| | return updatedAssistant; |
| | } |
| | return assistant; |
| | }), |
| | }, |
| | ); |
| |
|
| | queryClient.setQueryData<t.Action[]>([QueryKeys.actions], (prev) => { |
| | return prev |
| | ?.map((action) => { |
| | if (action.action_id === variables.action_id) { |
| | return updateActionResponse[2]; |
| | } |
| | return action; |
| | }) |
| | .concat( |
| | variables.action_id != null && variables.action_id ? [] : [updateActionResponse[2]], |
| | ); |
| | }); |
| |
|
| | return options?.onSuccess?.(updateActionResponse, variables, context); |
| | }, |
| | }); |
| | }; |
| |
|
| | |
| | |
| | |
| | export const useDeleteAction = ( |
| | options?: t.DeleteActionOptions, |
| | ): UseMutationResult< |
| | void, |
| | Error, |
| | t.DeleteActionVariables, |
| | unknown |
| | > => { |
| | const queryClient = useQueryClient(); |
| | return useMutation([MutationKeys.deleteAction], { |
| | mutationFn: (variables: t.DeleteActionVariables) => { |
| | const { endpoint } = variables; |
| | const endpointsConfig = queryClient.getQueryData<t.TEndpointsConfig>([QueryKeys.endpoints]); |
| | const version = endpointsConfig?.[endpoint]?.version ?? defaultAssistantsVersion[endpoint]; |
| | return dataService.deleteAction({ |
| | ...variables, |
| | version, |
| | }); |
| | }, |
| |
|
| | onMutate: (variables) => options?.onMutate?.(variables), |
| | onError: (error, variables, context) => options?.onError?.(error, variables, context), |
| | onSuccess: (_data, variables, context) => { |
| | let domain: string | undefined = ''; |
| | queryClient.setQueryData<t.Action[]>([QueryKeys.actions], (prev) => { |
| | return prev?.filter((action) => { |
| | domain = action.metadata.domain; |
| | return action.action_id !== variables.action_id; |
| | }); |
| | }); |
| |
|
| | queryClient.setQueryData<t.AssistantListResponse>( |
| | [QueryKeys.assistants, variables.endpoint, defaultOrderQuery], |
| | (prev) => { |
| | if (!prev) { |
| | return prev; |
| | } |
| |
|
| | return { |
| | ...prev, |
| | data: prev.data.map((assistant) => { |
| | if (assistant.id === variables.assistant_id) { |
| | return { |
| | ...assistant, |
| | tools: (assistant.tools ?? []).filter( |
| | (tool) => !(tool.function?.name.includes(domain ?? '') ?? false), |
| | ), |
| | }; |
| | } |
| | return assistant; |
| | }), |
| | }; |
| | }, |
| | ); |
| |
|
| | return options?.onSuccess?.(_data, variables, context); |
| | }, |
| | }); |
| | }; |
| |
|
| | |
| | |
| | |
| | export const useVerifyEmailMutation = ( |
| | options?: t.VerifyEmailOptions, |
| | ): UseMutationResult<t.VerifyEmailResponse, unknown, t.TVerifyEmail, unknown> => { |
| | return useMutation({ |
| | mutationFn: (variables: t.TVerifyEmail) => dataService.verifyEmail(variables), |
| | ...(options || {}), |
| | }); |
| | }; |
| |
|
| | |
| | |
| | |
| | export const useResendVerificationEmail = ( |
| | options?: t.ResendVerifcationOptions, |
| | ): UseMutationResult<t.VerifyEmailResponse, unknown, t.TResendVerificationEmail, unknown> => { |
| | return useMutation({ |
| | mutationFn: (variables: t.TResendVerificationEmail) => |
| | dataService.resendVerificationEmail(variables), |
| | ...(options || {}), |
| | }); |
| | }; |
| |
|
| | export const useAcceptTermsMutation = ( |
| | options?: t.AcceptTermsMutationOptions, |
| | ): UseMutationResult<t.TAcceptTermsResponse, unknown, void, unknown> => { |
| | const queryClient = useQueryClient(); |
| | return useMutation(() => dataService.acceptTerms(), { |
| | onSuccess: (data, variables, context) => { |
| | queryClient.setQueryData<t.TUserTermsResponse>([QueryKeys.userTerms], { |
| | termsAccepted: true, |
| | }); |
| | options?.onSuccess?.(data, variables, context); |
| | }, |
| | onError: options?.onError, |
| | onMutate: options?.onMutate, |
| | }); |
| | }; |
| |
|