🔀 feat: Save & Submit Message Content Parts (#8171)

* 🐛 fix: Enhance provider validation and error handling in getProviderConfig function

* WIP: edit text part

* refactor: Allow updating of both TEXT and THINK content types in message updates

* WIP: first pass, save & submit

* chore: remove legacy generation user message field

* feat: merge edited content

* fix: update placeholder and description for bedrock setting

* fix: remove unsupported warning message for AI resubmission
This commit is contained in:
Danny Avila 2025-07-01 15:43:10 -04:00 committed by GitHub
parent a648ad3d13
commit 434289fe92
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 240 additions and 84 deletions

View file

@ -81,14 +81,23 @@ const ContentParts = memo(
return (
<>
{content.map((part, idx) => {
if (part?.type !== ContentTypes.TEXT || typeof part.text !== 'string') {
if (!part) {
return null;
}
const isTextPart =
part?.type === ContentTypes.TEXT ||
typeof (part as unknown as Agents.MessageContentText)?.text !== 'string';
const isThinkPart =
part?.type === ContentTypes.THINK ||
typeof (part as unknown as Agents.ReasoningDeltaUpdate)?.think !== 'string';
if (!isTextPart && !isThinkPart) {
return null;
}
return (
<EditTextPart
index={idx}
text={part.text}
part={part as Agents.MessageContentText | Agents.ReasoningDeltaUpdate}
messageId={messageId}
isSubmitting={isSubmitting}
enterEdit={enterEdit}

View file

@ -1,8 +1,9 @@
import { useRef, useEffect, useCallback, useMemo } from 'react';
import { useForm } from 'react-hook-form';
import { ContentTypes } from 'librechat-data-provider';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useRef, useEffect, useCallback, useMemo } from 'react';
import { useUpdateMessageContentMutation } from 'librechat-data-provider/react-query';
import type { Agents } from 'librechat-data-provider';
import type { TEditProps } from '~/common';
import Container from '~/components/Chat/Messages/Content/Container';
import { useChatContext, useAddedChatContext } from '~/Providers';
@ -12,18 +13,19 @@ import { useLocalize } from '~/hooks';
import store from '~/store';
const EditTextPart = ({
text,
part,
index,
messageId,
isSubmitting,
enterEdit,
}: Omit<TEditProps, 'message' | 'ask'> & {
}: Omit<TEditProps, 'message' | 'ask' | 'text'> & {
index: number;
messageId: string;
part: Agents.MessageContentText | Agents.ReasoningDeltaUpdate;
}) => {
const localize = useLocalize();
const { addedIndex } = useAddedChatContext();
const { getMessages, setMessages, conversation } = useChatContext();
const { ask, getMessages, setMessages, conversation } = useChatContext();
const [latestMultiMessage, setLatestMultiMessage] = useRecoilState(
store.latestMessageFamily(addedIndex),
);
@ -34,15 +36,16 @@ const EditTextPart = ({
[getMessages, messageId],
);
const chatDirection = useRecoilValue(store.chatDirection);
const textAreaRef = useRef<HTMLTextAreaElement | null>(null);
const updateMessageContentMutation = useUpdateMessageContentMutation(conversationId ?? '');
const chatDirection = useRecoilValue(store.chatDirection).toLowerCase();
const isRTL = chatDirection === 'rtl';
const isRTL = chatDirection?.toLowerCase() === 'rtl';
const { register, handleSubmit, setValue } = useForm({
defaultValues: {
text: text ?? '',
text: (ContentTypes.THINK in part ? part.think : part.text) || '',
},
});
@ -55,15 +58,7 @@ const EditTextPart = ({
}
}, []);
/*
const resubmitMessage = () => {
showToast({
status: 'warning',
message: localize('com_warning_resubmit_unsupported'),
});
// const resubmitMessage = (data: { text: string }) => {
// Not supported by AWS Bedrock
const resubmitMessage = (data: { text: string }) => {
const messages = getMessages();
const parentMessage = messages?.find((msg) => msg.messageId === message?.parentMessageId);
@ -73,17 +68,19 @@ const EditTextPart = ({
ask(
{ ...parentMessage },
{
editedText: data.text,
editedContent: {
index,
text: data.text,
type: part.type,
},
editedMessageId: messageId,
isRegenerate: true,
isEdited: true,
},
);
setSiblingIdx((siblingIdx ?? 0) - 1);
enterEdit(true);
};
*/
const updateMessage = (data: { text: string }) => {
const messages = getMessages();
@ -167,13 +164,13 @@ const EditTextPart = ({
/>
</div>
<div className="mt-2 flex w-full justify-center text-center">
{/* <button
<button
className="btn btn-primary relative mr-2"
disabled={isSubmitting}
onClick={handleSubmit(resubmitMessage)}
>
{localize('com_ui_save_submit')}
</button> */}
</button>
<button
className="btn btn-secondary relative mr-2"
disabled={isSubmitting}