diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index f384c5b8f..cabb35d61 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -42,6 +42,7 @@ import FilesOverlay from './MessageInput/FilesOverlay.svelte'; import Commands from './MessageInput/Commands.svelte'; import ToolServersModal from './ToolServersModal.svelte'; + import VariableInputModal from './VariableInputModal.svelte'; import RichTextInput from '../common/RichTextInput.svelte'; import Tooltip from '../common/Tooltip.svelte'; @@ -89,6 +90,10 @@ export let webSearchEnabled = false; export let codeInterpreterEnabled = false; + let showVariableInputModal = false; + let activePromptVariables = []; + const RESERVED_VARIABLES = ['CLIPBOARD', 'USER_LOCATION', 'USER_NAME', 'USER_LANGUAGE', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_DATETIME', 'CURRENT_TIMEZONE', 'CURRENT_WEEKDAY']; + $: onChange({ prompt, files: files @@ -453,6 +458,18 @@ shiftKey = false; }; + const extractCustomVariables = (text: string): string[] => { + const regex = /{{\s*(.*?)\s*}}/g; + const matches = []; + let match; + while ((match = regex.exec(text)) !== null) { + matches.push(match[1]); + } + return [...new Set(matches)].filter(v => !RESERVED_VARIABLES.includes(v.toUpperCase())); + }; + + const variableModalSubtitle = $i18n.t('Your prompt uses the highlighted variables as placeholders'); + onMount(async () => { loaded = true; @@ -496,6 +513,31 @@ + { + const submittedValues = e.detail; + let currentPrompt = prompt; + for (const variable in submittedValues) { + const value = submittedValues[variable]; + const regex = new RegExp(`{{\\s*${variable}\\s*}}`, 'g'); + currentPrompt = currentPrompt.replace(regex, value); + } + prompt = currentPrompt; + showVariableInputModal = false; + activePromptVariables = []; + + tick().then(() => { + const chatInput = document.getElementById('chat-input'); + if (chatInput) { + chatInput.focus(); + } + }); + }} +/> {#if loaded}
@@ -586,6 +628,15 @@ const chatInputElement = document.getElementById('chat-input'); chatInputElement?.focus(); }} + on:promptselectionprocessed={(e) => { + const customVars = extractCustomVariables(prompt); + if (customVars.length > 0) { + activePromptVariables = customVars; + showVariableInputModal = true; + } + const chatInputElement = document.getElementById('chat-input'); + chatInputElement?.focus(); + }} />
diff --git a/src/lib/components/chat/MessageInput/Commands.svelte b/src/lib/components/chat/MessageInput/Commands.svelte index bcea28d1e..4339456aa 100644 --- a/src/lib/components/chat/MessageInput/Commands.svelte +++ b/src/lib/components/chat/MessageInput/Commands.svelte @@ -56,7 +56,8 @@ {#if show} {#if !loading} {#if command?.charAt(0) === '/'} - + dispatch('promptselectionprocessed', e.detail)} /> {:else if (command?.charAt(0) === '#' && command.startsWith('#') && !command.includes('# ')) || ('\\#' === command.slice(0, 2) && command.startsWith('#') && !command.includes('# '))} diff --git a/src/lib/components/chat/VariableInputModal.svelte b/src/lib/components/chat/VariableInputModal.svelte new file mode 100644 index 000000000..2de2d6222 --- /dev/null +++ b/src/lib/components/chat/VariableInputModal.svelte @@ -0,0 +1,132 @@ + + + +
+
+

{$i18n.t('Enter Variable Values')}

+ +
+ {#if subtitle} +

{@html subtitle}

+ {/if} + + {#if promptRawContent} +
+ {@html formattedPromptDisplay} +
+ {/if} + +

{$i18n.t('You may replace the placeholder variables with values below. Note that if you do not enter a value, the placeholder will be removed from the text.')}

+ +
+ {#each variables as variable (variable)} +
+
+ {@html $i18n.t('Insert a value for {{variable}}', { variable })} +
+