diff --git a/libs/shared/data-access/api/src/lib/chats/api.ts b/libs/shared/data-access/api/src/lib/chats/api.ts index 1957c8da..c6c1bf66 100644 --- a/libs/shared/data-access/api/src/lib/chats/api.ts +++ b/libs/shared/data-access/api/src/lib/chats/api.ts @@ -30,7 +30,6 @@ import { ChatResponse, CompleteChatRequest, CompleteChatResponse, - CompletedChat, CreateNewChatRequest, GetArchivedChatListRequest, MoveChatToFolderRequest, @@ -553,15 +552,6 @@ function useCompleteChat( }); } -function useCompletedChat( - options?: UseMutationOptions, -): UseMutationResult { - return useMutation({ - mutationFn: (params) => chatService.handleCompletedChat(params), - ...options, - }); -} - function useShareChat({ onSuccess, ...options @@ -818,7 +808,6 @@ export const chatApi = { useSearchInfinite, useCreateNewChat, useCompleteChat, - useCompletedChat, useShareChat, useDeleteShareChatLink, useArchiveChat, diff --git a/libs/shared/data-access/api/src/lib/chats/models/completed-chat.ts b/libs/shared/data-access/api/src/lib/chats/models/completed-chat.ts deleted file mode 100644 index f1ac941b..00000000 --- a/libs/shared/data-access/api/src/lib/chats/models/completed-chat.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Expose } from 'class-transformer'; -import { Message } from './message'; - -export class CompletedChat { - @Expose({ name: 'chat_id' }) - public chatId: string; - - @Expose() - public id: string; - - @Expose() - public messages: Array>; - - @Expose() - public model: string; - - @Expose({ name: 'session_id' }) - public sessionId: string; - - constructor(completedChat: Partial = {}) { - Object.assign(this, completedChat); - } -} diff --git a/libs/shared/data-access/api/src/lib/chats/models/index.ts b/libs/shared/data-access/api/src/lib/chats/models/index.ts index 6ae79a06..75e9aacc 100644 --- a/libs/shared/data-access/api/src/lib/chats/models/index.ts +++ b/libs/shared/data-access/api/src/lib/chats/models/index.ts @@ -8,7 +8,6 @@ export * from './complete-chat-response'; export * from './background-tasks'; export * from './get-chat-list-request'; export * from './chat-list-item'; -export * from './completed-chat'; export * from './search-chat-list-request'; export * from './share-chat-response'; export * from './chat-message'; diff --git a/libs/shared/data-access/api/src/lib/chats/service.ts b/libs/shared/data-access/api/src/lib/chats/service.ts index 42b6dfda..29b23e2a 100644 --- a/libs/shared/data-access/api/src/lib/chats/service.ts +++ b/libs/shared/data-access/api/src/lib/chats/service.ts @@ -8,7 +8,6 @@ import { ChatResponse, CompleteChatRequest, CompleteChatResponse, - CompletedChat, CreateNewChatRequest, GetArchivedChatListRequest, GetChatListRequest, @@ -129,14 +128,6 @@ export class ChatService extends EntityPromiseService { ); } - public async handleCompletedChat(params: CompletedChat): Promise { - const request = instanceToPlain(params); - - const response = await getApiService().post(`${chatServiceConfig.route}/completed`, request); - - return plainToInstance(CompletedChat, response); - } - public async shareChat(chatId: string): Promise { const response = await getApiService().post( `${chatServiceConfig.versionedRoute}/${chatId}/share`, diff --git a/libs/shared/data-access/api/src/lib/chats/utils/handle-completed-chat.ts b/libs/shared/data-access/api/src/lib/chats/utils/handle-completed-chat.ts index 95d62d11..83374409 100644 --- a/libs/shared/data-access/api/src/lib/chats/utils/handle-completed-chat.ts +++ b/libs/shared/data-access/api/src/lib/chats/utils/handle-completed-chat.ts @@ -1,17 +1,20 @@ import { merge, uniqBy } from 'lodash-es'; -import { captureApiError } from '@open-webui-react-native/shared/data-access/api-client'; import { AttachedFile, FileType, MessageSource } from '@open-webui-react-native/shared/data-access/common'; import { queryClient } from '@open-webui-react-native/shared/data-access/query-client'; import { chatQueriesKeys } from '../chat-queries-keys'; import { Chat, ChatResponse, History, Message } from '../models'; import { chatService } from '../service'; -import { prepareCompletedChatPayload } from './prepare-completed-chat-payload'; import { isTemporaryChatId } from './temporary-chat-id'; +// NOTE: Deliberately does not call `POST /chat/completed`. The app supports Open WebUI 0.10 and +// newer, and since 0.9.0 the backend runs outlet filters inline during the completion and persists +// the assistant message itself — the web client dropped the call in that same release, leaving it +// for external integrations only. Calling it re-ran the filters on a payload this client discards, +// and the endpoint turns every internal error into a 400 (a missing `model`, a stale `session_id`, +// a throwing filter), which used to abort the chat update below. export const handleCompletedChat = async ( message: string, chatId: string, - sessionId: string, sources?: Array, output?: Message['output'], ): Promise => { @@ -43,15 +46,6 @@ export const handleCompletedChat = async ( currentId: chat.history.currentId, }); - const completedChatPayload = prepareCompletedChatPayload( - chatId, - updatedHistory.currentId, - updatedMessages, - chat.models?.[0], - sessionId, - message, - ); - // Only files should be included in `files` field const files = uniqBy( chat.messages.flatMap((msg) => msg.files ?? []).filter((file): file is AttachedFile => file.type === FileType.FILE), @@ -64,17 +58,5 @@ export const handleCompletedChat = async ( files, }); - const sentryContext = { chatId, sessionId }; - - try { - const data = await chatService.handleCompletedChat(completedChatPayload); - - try { - await chatService.update({ id: data.chatId, chat: updateChatPayload }); - } catch (error) { - captureApiError(error, { operation: 'chat.update', context: sentryContext }); - } - } catch (error) { - captureApiError(error, { operation: 'chat.completed', context: sentryContext }); - } + await chatService.update({ id: chatId, chat: updateChatPayload }); }; diff --git a/libs/shared/data-access/api/src/lib/chats/utils/index.ts b/libs/shared/data-access/api/src/lib/chats/utils/index.ts index 5453d52c..50e5abb9 100644 --- a/libs/shared/data-access/api/src/lib/chats/utils/index.ts +++ b/libs/shared/data-access/api/src/lib/chats/utils/index.ts @@ -1,6 +1,5 @@ export * from './prepare-create-chat-payload'; export * from './prepare-complete-chat-payload'; -export * from './prepare-completed-chat-payload'; export * from './prepare-send-message-payload'; export * from './patch-chat-message-with-completion'; export * from './patch-completed-message'; diff --git a/libs/shared/data-access/api/src/lib/chats/utils/prepare-completed-chat-payload.ts b/libs/shared/data-access/api/src/lib/chats/utils/prepare-completed-chat-payload.ts deleted file mode 100644 index 1e5e641d..00000000 --- a/libs/shared/data-access/api/src/lib/chats/utils/prepare-completed-chat-payload.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Role } from '@open-webui-react-native/shared/data-access/common'; -import { CompletedChat, Message } from '../models'; - -export function prepareCompletedChatPayload( - chatId: string, - id: string, - messages: Array, - model: string, - sessionId: string, - generatedMessage: string, -): CompletedChat { - const preparedMessages = messages.reduce< - Array<{ - content: string; - id: string; - role: Role; - timestamp: number; - }> - >((acc, m, index) => { - const isLast = index === messages.length - 1; - - acc.push({ - content: isLast ? generatedMessage : m.content, - id: m.id, - role: m.role, - timestamp: m.timestamp, - }); - - return acc; - }, []); - - return new CompletedChat({ - chatId, - id, - messages: preparedMessages, - model, - sessionId, - }); -} diff --git a/libs/shared/data-access/api/src/lib/chats/utils/socket-events/handle-chat-completion-event.ts b/libs/shared/data-access/api/src/lib/chats/utils/socket-events/handle-chat-completion-event.ts index c89a8698..76e028c0 100644 --- a/libs/shared/data-access/api/src/lib/chats/utils/socket-events/handle-chat-completion-event.ts +++ b/libs/shared/data-access/api/src/lib/chats/utils/socket-events/handle-chat-completion-event.ts @@ -5,7 +5,6 @@ import { ChatCompletionChunk, getOutputText, seedResponseStreamState, - socketService, } from '@open-webui-react-native/shared/data-access/websocket'; import { hapticFeedbackService } from '@open-webui-react-native/shared/utils/haptic-feedback-service'; import { chatQueriesKeys } from '../../chat-queries-keys'; @@ -25,7 +24,6 @@ import { // event is left carrying the tool-call boundaries and the terminal `done`. Both remain authoritative, // which is why a snapshot also re-seeds the delta accumulator. export const handleChatCompletionEvent = async (socketResponse: ChatEventBase): Promise => { - const sessionId = socketService.socketSessionId; const chatId = socketResponse.chatId; const chatCompletionData = plainToInstance(ChatCompletionChunk, socketResponse.data.data); @@ -66,7 +64,7 @@ export const handleChatCompletionEvent = async (socketResponse: ChatEventBase): queryClient.setQueryData(chatQueriesKeys.get(chatId).queryKey, (oldData: ChatResponse) => patchCompletedMessage(oldData), ); - await handleCompletedChat(buffer.content, chatId, sessionId, buffer.sources, buffer.output); + await handleCompletedChat(buffer.content, chatId, buffer.sources, buffer.output); resetChatStreamBuffer(chatId); await hapticFeedbackService.trigger(); }