Skip to content

Commit 6fb52a4

Browse files
committed
feat: add plain regenerate response action
1 parent e1bafe4 commit 6fb52a4

File tree

11 files changed

+92
-10
lines changed

11 files changed

+92
-10
lines changed

dist/components/Bot.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/components/bubbles/BotBubble.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type Props = {
2121
renderHTML?: boolean;
2222
handleActionClick: (elem: any, action: IAction | undefined | null) => void;
2323
handleSourceDocumentsClick: (src: any) => void;
24+
onRegenerateResponse?: () => void;
2425
isTTSEnabled?: boolean;
2526
isTTSLoading?: Record<string, boolean>;
2627
isTTSPlaying?: Record<string, boolean>;

dist/components/bubbles/BotBubble.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { JSX } from 'solid-js';
2+
type RegenerateResponseButtonProps = {
3+
feedbackColor?: string;
4+
isDisabled?: boolean;
5+
isLoading?: boolean;
6+
disableIcon?: boolean;
7+
} & JSX.ButtonHTMLAttributes<HTMLButtonElement>;
8+
export declare const RegenerateResponseButton: (props: RegenerateResponseButtonProps) => JSX.Element;
9+
export {};
10+
//# sourceMappingURL=RegenerateResponseButton.d.ts.map

dist/components/buttons/RegenerateResponseButton.d.ts.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/web.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/web.umd.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/assets/index.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@ textarea {
272272
stroke: var(--chatbot-button-color);
273273
}
274274

275+
.regenerate-response-button > .icon-tabler-refresh {
276+
width: 16px;
277+
height: 16px;
278+
}
279+
275280
.chatbot-chat-view {
276281
max-width: 800px;
277282
}

src/components/Bot.tsx

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,28 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
881881
handleSubmit(prompt);
882882
};
883883

884+
const handleRegenerateResponse = async (messageIndex: number) => {
885+
if (loading()) return;
886+
if (previews().length) return;
887+
if (startInputType() === 'formInput') return;
888+
889+
const currentMessages = messages();
890+
const targetMessage = currentMessages[messageIndex];
891+
if (!targetMessage || targetMessage.type !== 'apiMessage') return;
892+
893+
const previousMessage = currentMessages[messageIndex - 1];
894+
if (!previousMessage || previousMessage.type !== 'userMessage' || previousMessage.fileUploads?.length) return;
895+
896+
setFollowUpPrompts([]);
897+
const updatedMessages = currentMessages.slice(0, messageIndex);
898+
addChatMessage(updatedMessages);
899+
setMessages(updatedMessages);
900+
901+
// Note: chatId is kept so the server retains conversation context up to this point.
902+
// The server's history will still include messages that were removed client-side
903+
await handleSubmit(previousMessage.message, undefined, undefined, { skipAddUserMessage: true });
904+
};
905+
884906
const updateMetadata = (data: any, input: string) => {
885907
if (data.chatId) {
886908
setChatId(data.chatId);
@@ -1157,7 +1179,12 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
11571179
};
11581180

11591181
// Handle form submission
1160-
const handleSubmit = async (value: string | object, action?: IAction | undefined | null, humanInput?: any) => {
1182+
const handleSubmit = async (
1183+
value: string | object,
1184+
action?: IAction | undefined | null,
1185+
humanInput?: any,
1186+
options?: { skipAddUserMessage?: boolean },
1187+
) => {
11611188
if (typeof value === 'string' && value.trim() === '') {
11621189
const containsFile = previews().filter((item) => !item.mime.startsWith('image') && item.type !== 'audio').length > 0;
11631190
if (!previews().length || (previews().length && containsFile)) {
@@ -1194,11 +1221,13 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
11941221

11951222
clearPreviews();
11961223

1197-
setMessages((prevMessages) => {
1198-
const messages: MessageType[] = [...prevMessages, { message: value as string, type: 'userMessage', fileUploads: uploads }];
1199-
addChatMessage(messages);
1200-
return messages;
1201-
});
1224+
if (!options?.skipAddUserMessage) {
1225+
setMessages((prevMessages) => {
1226+
const messages: MessageType[] = [...prevMessages, { message: value as string, type: 'userMessage', fileUploads: uploads }];
1227+
addChatMessage(messages);
1228+
return messages;
1229+
});
1230+
}
12021231

12031232
const body: IncomingInput = {
12041233
question: value,
@@ -2594,6 +2623,7 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
25942623
showAvatar={props.botMessage?.showAvatar}
25952624
avatarSrc={props.botMessage?.avatarSrc}
25962625
chatFeedbackStatus={chatFeedbackStatus()}
2626+
onRegenerateResponse={() => handleRegenerateResponse(index())}
25972627
fontSize={props.fontSize}
25982628
isLoading={loading() && index() === messages().length - 1}
25992629
showAgentMessages={props.showAgentMessages}

src/components/bubbles/BotBubble.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import DOMPurify from 'dompurify';
55
import { FeedbackRatingType, sendFeedbackQuery, sendFileDownloadQuery, updateFeedbackQuery } from '@/queries/sendMessageQuery';
66
import { FileUpload, IAction, MessageType } from '../Bot';
77
import { CopyToClipboardButton, ThumbsDownButton, ThumbsUpButton } from '../buttons/FeedbackButtons';
8+
import { RegenerateResponseButton } from '../buttons/RegenerateResponseButton';
89
import { TTSButton } from '../buttons/TTSButton';
910
import FeedbackContentDialog from '../FeedbackContentDialog';
1011
import { AgentReasoningBubble } from './AgentReasoningBubble';
@@ -35,6 +36,7 @@ type Props = {
3536
renderHTML?: boolean;
3637
handleActionClick: (elem: any, action: IAction | undefined | null) => void;
3738
handleSourceDocumentsClick: (src: any) => void;
39+
onRegenerateResponse?: () => void;
3840
// TTS props
3941
isTTSEnabled?: boolean;
4042
isTTSLoading?: Record<string, boolean>;
@@ -581,6 +583,7 @@ export const BotBubble = (props: Props) => {
581583
</Show>
582584
{props.chatFeedbackStatus && props.message.messageId && (
583585
<>
586+
<RegenerateResponseButton class="regenerate-response-button" feedbackColor={props.feedbackColor} onClick={() => props.onRegenerateResponse?.()} />
584587
<CopyToClipboardButton feedbackColor={props.feedbackColor} onClick={() => copyMessageToClipboard()} />
585588
<Show when={copiedMessage()}>
586589
<div class="copied-message" style={{ color: props.feedbackColor ?? defaultFeedbackColor }}>

0 commit comments

Comments
 (0)