enh: follow up prompts behaviour

This commit is contained in:
Timothy Jaeryang Baek 2025-07-18 17:49:24 +04:00
parent 5e4e1cf662
commit c414f0c3ce
7 changed files with 86 additions and 2 deletions

View file

@ -2123,6 +2123,9 @@
bind:history bind:history
bind:autoScroll bind:autoScroll
bind:prompt bind:prompt
setInputText={(text) => {
messageInput?.setText(text);
}}
{selectedModels} {selectedModels}
{atSelectedModel} {atSelectedModel}
{sendPrompt} {sendPrompt}

View file

@ -36,6 +36,8 @@
let messages = []; let messages = [];
export let setInputText: Function = () => {};
export let sendPrompt: Function; export let sendPrompt: Function;
export let continueResponse: Function; export let continueResponse: Function;
export let regenerateResponse: Function; export let regenerateResponse: Function;
@ -426,6 +428,7 @@
messageId={message.id} messageId={message.id}
idx={messageIdx} idx={messageIdx}
{user} {user}
{setInputText}
{gotoMessage} {gotoMessage}
{showPreviousMessage} {showPreviousMessage}
{showNextMessage} {showNextMessage}

View file

@ -21,6 +21,7 @@
export let user; export let user;
export let setInputText: Function = () => {};
export let gotoMessage; export let gotoMessage;
export let showPreviousMessage; export let showPreviousMessage;
export let showNextMessage; export let showNextMessage;
@ -74,6 +75,7 @@
{selectedModels} {selectedModels}
isLastMessage={messageId === history.currentId} isLastMessage={messageId === history.currentId}
siblings={history.messages[history.messages[messageId].parentId]?.childrenIds ?? []} siblings={history.messages[history.messages[messageId].parentId]?.childrenIds ?? []}
{setInputText}
{gotoMessage} {gotoMessage}
{showPreviousMessage} {showPreviousMessage}
{showNextMessage} {showNextMessage}
@ -96,6 +98,7 @@
{messageId} {messageId}
{selectedModels} {selectedModels}
isLastMessage={messageId === history?.currentId} isLastMessage={messageId === history?.currentId}
{setInputText}
{updateChat} {updateChat}
{editMessage} {editMessage}
{saveMessage} {saveMessage}

View file

@ -28,6 +28,7 @@
export let isLastMessage; export let isLastMessage;
export let readOnly = false; export let readOnly = false;
export let setInputText: Function = () => {};
export let updateChat: Function; export let updateChat: Function;
export let editMessage: Function; export let editMessage: Function;
export let saveMessage: Function; export let saveMessage: Function;
@ -259,6 +260,7 @@
gotoMessage={(message, messageIdx) => gotoMessage(modelIdx, messageIdx)} gotoMessage={(message, messageIdx) => gotoMessage(modelIdx, messageIdx)}
showPreviousMessage={() => showPreviousMessage(modelIdx)} showPreviousMessage={() => showPreviousMessage(modelIdx)}
showNextMessage={() => showNextMessage(modelIdx)} showNextMessage={() => showNextMessage(modelIdx)}
{setInputText}
{updateChat} {updateChat}
{editMessage} {editMessage}
{saveMessage} {saveMessage}

View file

@ -117,6 +117,7 @@
export let siblings; export let siblings;
export let setInputText: Function = () => {};
export let gotoMessage: Function = () => {}; export let gotoMessage: Function = () => {};
export let showPreviousMessage: Function; export let showPreviousMessage: Function;
export let showNextMessage: Function; export let showNextMessage: Function;
@ -1464,12 +1465,18 @@
/> />
{/if} {/if}
{#if isLastMessage && message.done && !readOnly && (message?.followUps ?? []).length > 0} {#if (isLastMessage || ($settings?.keepFollowUpPrompts ?? false)) && message.done && !readOnly && (message?.followUps ?? []).length > 0}
<div class="mt-2.5" in:fade={{ duration: 100 }}> <div class="mt-2.5" in:fade={{ duration: 100 }}>
<FollowUps <FollowUps
followUps={message?.followUps} followUps={message?.followUps}
onClick={(prompt) => { onClick={(prompt) => {
submitMessage(message?.id, prompt); if ($settings?.insertFollowUpPrompt ?? false) {
// Insert the follow-up prompt into the input box
setInputText(prompt);
} else {
// Submit the follow-up prompt directly
submitMessage(message?.id, prompt);
}
}} }}
/> />
</div> </div>

View file

@ -43,6 +43,9 @@
let largeTextAsFile = false; let largeTextAsFile = false;
let keepFollowUpPrompts = false;
let insertFollowUpPrompt = false;
let landingPageMode = ''; let landingPageMode = '';
let chatBubble = true; let chatBubble = true;
let chatDirection: 'LTR' | 'RTL' | 'auto' = 'auto'; let chatDirection: 'LTR' | 'RTL' | 'auto' = 'auto';
@ -230,6 +233,16 @@
saveSettings({ insertPromptAsRichText }); saveSettings({ insertPromptAsRichText });
}; };
const toggleKeepFollowUpPrompts = async () => {
keepFollowUpPrompts = !keepFollowUpPrompts;
saveSettings({ keepFollowUpPrompts });
};
const toggleInsertFollowUpPrompt = async () => {
insertFollowUpPrompt = !insertFollowUpPrompt;
saveSettings({ insertFollowUpPrompt });
};
const toggleLargeTextAsFile = async () => { const toggleLargeTextAsFile = async () => {
largeTextAsFile = !largeTextAsFile; largeTextAsFile = !largeTextAsFile;
saveSettings({ largeTextAsFile }); saveSettings({ largeTextAsFile });
@ -325,6 +338,9 @@
insertPromptAsRichText = $settings?.insertPromptAsRichText ?? false; insertPromptAsRichText = $settings?.insertPromptAsRichText ?? false;
promptAutocomplete = $settings?.promptAutocomplete ?? false; promptAutocomplete = $settings?.promptAutocomplete ?? false;
keepFollowUpPrompts = $settings?.keepFollowUpPrompts ?? false;
insertFollowUpPrompt = $settings?.insertFollowUpPrompt ?? false;
largeTextAsFile = $settings?.largeTextAsFile ?? false; largeTextAsFile = $settings?.largeTextAsFile ?? false;
copyFormatted = $settings?.copyFormatted ?? false; copyFormatted = $settings?.copyFormatted ?? false;
@ -777,6 +793,52 @@
</div> </div>
</div> </div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div id="keep-followup-prompts-label" class=" self-center text-xs">
{$i18n.t('Keep Follow-Up Prompts in Chat')}
</div>
<button
aria-labelledby="keep-followup-prompts-label"
class="p-1 px-3 text-xs flex rounded-sm transition"
on:click={() => {
toggleKeepFollowUpPrompts();
}}
type="button"
>
{#if keepFollowUpPrompts === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div id="insert-followup-prompt-label" class=" self-center text-xs">
{$i18n.t('Insert Follow-Up Prompt to Input')}
</div>
<button
aria-labelledby="insert-followup-prompt-label"
class="p-1 px-3 text-xs flex rounded-sm transition"
on:click={() => {
toggleInsertFollowUpPrompt();
}}
type="button"
>
{#if insertFollowUpPrompt === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
</div>
<div> <div>
<div class=" py-0.5 flex w-full justify-between"> <div class=" py-0.5 flex w-full justify-between">
<div id="rich-input-label" class=" self-center text-xs"> <div id="rich-input-label" class=" self-center text-xs">

View file

@ -655,6 +655,10 @@
export const setText = (text: string) => { export const setText = (text: string) => {
if (!editor) return; if (!editor) return;
text = text.replaceAll('\n\n', '\n'); text = text.replaceAll('\n\n', '\n');
// reset the editor content
editor.commands.clearContent();
const { state, view } = editor; const { state, view } = editor;
const { schema, tr } = state; const { schema, tr } = state;