diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte
index fd9ca1d54e..c18160331a 100644
--- a/src/lib/components/chat/MessageInput.svelte
+++ b/src/lib/components/chat/MessageInput.svelte
@@ -168,6 +168,13 @@
(history.currentId && history.messages[history.currentId]?.done != true) ||
generating);
$: canCompact = !!history?.currentId;
+ $: canToggleTemporary =
+ !embedded &&
+ !chatId &&
+ ($_user?.role === 'admin' ||
+ ($_user?.role === 'user' &&
+ ($_user?.permissions?.chat?.temporary ?? true) &&
+ !($_user?.permissions?.chat?.temporary_enforced ?? false)));
export let prompt = '';
export let files = [];
@@ -539,6 +546,26 @@
chatInputElement?.replaceCommandWithText(text);
};
+ const temporaryHandler = async () => {
+ if (!canToggleTemporary) return;
+
+ if (($settings?.temporaryChatByDefault ?? false) && $temporaryChatEnabled) {
+ await temporaryChatEnabled.set(null);
+ } else {
+ await temporaryChatEnabled.set(!$temporaryChatEnabled);
+ }
+
+ if (location.pathname !== '/') {
+ await goto('/');
+ }
+
+ if ($temporaryChatEnabled) {
+ window.history.replaceState(null, '', '?temporary-chat=true');
+ } else {
+ window.history.replaceState(null, '', location.pathname);
+ }
+ };
+
const insertTextAtCursor = async (text: string) => {
const chatInput = document.getElementById('chat-input');
if (!chatInput) return;
@@ -1281,7 +1308,7 @@
return;
}
- if (['compact', 'fork', 'status', 'model'].includes(props?.id)) {
+ if (['compact', 'fork', 'status', 'model', 'settings', 'temporary'].includes(props?.id)) {
editor.chain().focus().deleteRange(range).run();
return;
}
@@ -1307,11 +1334,15 @@
!!history?.currentId &&
($_user?.role === 'admin' || ($_user?.permissions?.chat?.import ?? true)),
forkDisabled: () => isActive,
+ canTemporary: () => canToggleTemporary,
+ temporaryEnabled: () => $temporaryChatEnabled === true,
contextUsage: () => statusContextUsage,
onCompact: compactHandler,
onStatus: statusHandler,
onFork: forkHandler,
onModel: () => modelSelector?.open(),
+ onSettings: () => showSettings.set(true),
+ onTemporary: temporaryHandler,
onSelect: (e) => {
const { type, data } = e;
diff --git a/src/lib/components/chat/MessageInput/CommandSuggestionList.svelte b/src/lib/components/chat/MessageInput/CommandSuggestionList.svelte
index bc561bac11..deea60f895 100644
--- a/src/lib/components/chat/MessageInput/CommandSuggestionList.svelte
+++ b/src/lib/components/chat/MessageInput/CommandSuggestionList.svelte
@@ -21,12 +21,16 @@
export let onStatus: () => void = () => {};
export let onFork: () => void = () => {};
export let onModel: () => void = () => {};
+ export let onSettings: () => void = () => {};
+ export let onTemporary: () => void = () => {};
export let insertTextHandler: (text: string) => void = () => {};
export let canCompact: boolean | (() => boolean) = false;
export let compactDisabled: boolean | (() => boolean) = false;
export let canStatus: boolean | (() => boolean) = false;
export let canFork: boolean | (() => boolean) = false;
export let forkDisabled: boolean | (() => boolean) = false;
+ export let canTemporary: boolean | (() => boolean) = false;
+ export let temporaryEnabled: boolean | (() => boolean) = false;
export let contextUsage = null;
$: compactAvailable = typeof canCompact === 'function' ? canCompact() : canCompact;
@@ -35,6 +39,9 @@
$: statusAvailable = typeof canStatus === 'function' ? canStatus() : canStatus;
$: forkAvailable = typeof canFork === 'function' ? canFork() : canFork;
$: isForkDisabled = typeof forkDisabled === 'function' ? forkDisabled() : forkDisabled;
+ $: temporaryAvailable = typeof canTemporary === 'function' ? canTemporary() : canTemporary;
+ $: isTemporaryEnabled =
+ typeof temporaryEnabled === 'function' ? temporaryEnabled() : temporaryEnabled;
$: resolvedContextUsage = typeof contextUsage === 'function' ? contextUsage() : contextUsage;
$: contextHasThreshold = Number(resolvedContextUsage?.threshold) > 0;
$: contextPercent = contextHasThreshold
@@ -93,6 +100,8 @@
canStatus={statusAvailable}
canFork={forkAvailable}
forkDisabled={isForkDisabled}
+ canTemporary={temporaryAvailable}
+ temporaryEnabled={isTemporaryEnabled}
{contextPercent}
{contextHasThreshold}
onSelect={(e) => {
@@ -117,6 +126,12 @@
} else if (type === 'command' && data.id === 'model') {
command({ id: data.id, label: data.id });
onModel();
+ } else if (type === 'command' && data.id === 'settings') {
+ command({ id: data.id, label: data.id });
+ onSettings();
+ } else if (type === 'command' && data.id === 'temporary') {
+ command({ id: data.id, label: data.id });
+ onTemporary();
} else if (type === 'skill') {
command({
id: `${data.id}|${data.name}`,
diff --git a/src/lib/components/chat/MessageInput/Commands/SlashCommands.svelte b/src/lib/components/chat/MessageInput/Commands/SlashCommands.svelte
index e8129776c4..9b438ad2c1 100644
--- a/src/lib/components/chat/MessageInput/Commands/SlashCommands.svelte
+++ b/src/lib/components/chat/MessageInput/Commands/SlashCommands.svelte
@@ -3,7 +3,10 @@
import { getPrompts } from '$lib/apis/prompts';
import { getSkillItems } from '$lib/apis/skills';
import Tooltip from '$lib/components/common/Tooltip.svelte';
+ import ChatBubbleDotted from '$lib/components/icons/ChatBubbleDotted.svelte';
+ import ChatBubbleDottedChecked from '$lib/components/icons/ChatBubbleDottedChecked.svelte';
import Cube from '$lib/components/icons/Cube.svelte';
+ import Knobs from '$lib/components/icons/Knobs.svelte';
import Sparkles from '$lib/components/icons/Sparkles.svelte';
const i18n = getContext('i18n');
@@ -15,6 +18,8 @@
export let canStatus = false;
export let canFork = false;
export let forkDisabled = false;
+ export let canTemporary = false;
+ export let temporaryEnabled = false;
export let contextPercent = 0;
export let contextHasThreshold = false;
@@ -31,6 +36,9 @@
$: contextCircleOffset = 50.27 * (1 - contextCirclePercent / 100);
$: commandItems = [
+ ...(canTemporary && 'temporary'.startsWith(query.toLowerCase())
+ ? [{ type: 'command', data: { id: 'temporary' } }]
+ : []),
...(canCompact && 'compact'.startsWith(query.toLowerCase())
? [{ type: 'command', data: { id: 'compact' } }]
: []),
@@ -40,7 +48,12 @@
...(canStatus && 'status'.startsWith(query.toLowerCase())
? [{ type: 'command', data: { id: 'status' } }]
: []),
- ...('model'.startsWith(query.toLowerCase()) ? [{ type: 'command', data: { id: 'model' } }] : [])
+ ...('model'.startsWith(query.toLowerCase())
+ ? [{ type: 'command', data: { id: 'model' } }]
+ : []),
+ ...('settings'.startsWith(query.toLowerCase())
+ ? [{ type: 'command', data: { id: 'settings' } }]
+ : [])
];
$: filteredPrompts = prompts
@@ -128,7 +141,39 @@
{#each commandItems as item, commandIdx}
- {#if item.data.id === 'compact'}
+ {#if item.data.id === 'temporary'}
+
+
+
+ {:else if item.data.id === 'compact'}
+ {:else if item.data.id === 'settings'}
+
+
+
{/if}
{/each}
{/if}