diff --git a/web/src/app/chat/input-prompts/InputPrompts.tsx b/web/src/app/chat/input-prompts/InputPrompts.tsx
index 0cf6ce546ab8..02dd93bb8e80 100644
--- a/web/src/app/chat/input-prompts/InputPrompts.tsx
+++ b/web/src/app/chat/input-prompts/InputPrompts.tsx
@@ -1,8 +1,8 @@
-import React, { useState, useEffect } from "react";
+import React, { useState, useEffect, useCallback } from "react";
import { InputPrompt } from "@/app/chat/interfaces";
import { Button } from "@/components/ui/button";
-import { TrashIcon, PlusIcon } from "@/components/icons/icons";
-import { MoreVertical, CheckIcon, XIcon } from "lucide-react";
+import { PlusIcon } from "@/components/icons/icons";
+import { MoreVertical, XIcon } from "lucide-react";
import { Textarea } from "@/components/ui/textarea";
import Title from "@/components/ui/title";
import Text from "@/components/ui/text";
@@ -153,114 +153,6 @@ export default function InputPrompts() {
}
};
- const PromptCard = ({ prompt }: { prompt: InputPrompt }) => {
- const isEditing = editingPromptId === prompt.id;
- const [localPrompt, setLocalPrompt] = useState(prompt.prompt);
- const [localContent, setLocalContent] = useState(prompt.content);
-
- // Sync local edits with any prompt changes from outside
- useEffect(() => {
- setLocalPrompt(prompt.prompt);
- setLocalContent(prompt.content);
- }, [prompt, isEditing]);
-
- const handleLocalEdit = (field: "prompt" | "content", value: string) => {
- if (field === "prompt") {
- setLocalPrompt(value);
- } else {
- setLocalContent(value);
- }
- };
-
- const handleSaveLocal = () => {
- handleSave(prompt.id, localPrompt, localContent);
- };
-
- return (
-
- {isEditing ? (
- <>
-
- {
- setEditingPromptId(null);
- fetchInputPrompts(); // Revert changes from server
- }}
- >
-
-
-
-
-
-
-
-
- {prompt.id ? "Save" : "Create"}
-
-
-
- >
- ) : (
- <>
-
-
-
-
-
{prompt.prompt}
- {isPromptPublic(prompt) &&
}
-
-
- {isPromptPublic(prompt) && (
-
- This is a built-in prompt and cannot be edited
-
- )}
-
-
-
{prompt.content}
-
-
-
-
-
-
-
-
- {!isPromptPublic(prompt) && (
- handleEdit(prompt.id)}>
- Edit
-
- )}
- handleDelete(prompt.id)}>
- Delete
-
-
-
-
- >
- )}
-
- );
- };
-
return (
@@ -272,13 +164,21 @@ export default function InputPrompts() {
Prompt Shortcuts
Manage and customize prompt shortcuts for your assistants. Use your
- prompt shortcuts by starting a new message “/” in chat.
+ prompt shortcuts by starting a new message with "/" in
+ chat.
{inputPrompts.map((prompt) => (
-
+
))}
{isCreatingNew ? (
@@ -315,3 +215,129 @@ export default function InputPrompts() {
);
}
+
+interface PromptCardProps {
+ prompt: InputPrompt;
+ onEdit: (id: number) => void;
+ onSave: (id: number, prompt: string, content: string) => void;
+ onDelete: (id: number) => void;
+ isEditing: boolean;
+}
+
+const PromptCard: React.FC = ({
+ prompt,
+ onEdit,
+ onSave,
+ onDelete,
+ isEditing,
+}) => {
+ const [localPrompt, setLocalPrompt] = useState(prompt.prompt);
+ const [localContent, setLocalContent] = useState(prompt.content);
+
+ useEffect(() => {
+ setLocalPrompt(prompt.prompt);
+ setLocalContent(prompt.content);
+ }, [prompt, isEditing]);
+
+ const handleLocalEdit = useCallback(
+ (field: "prompt" | "content", value: string) => {
+ if (field === "prompt") {
+ setLocalPrompt(value);
+ } else {
+ setLocalContent(value);
+ }
+ },
+ []
+ );
+
+ const handleSaveLocal = useCallback(() => {
+ onSave(prompt.id, localPrompt, localContent);
+ }, [prompt.id, localPrompt, localContent, onSave]);
+
+ const isPromptPublic = useCallback((p: InputPrompt): boolean => {
+ return p.is_public;
+ }, []);
+
+ return (
+
+ {isEditing ? (
+ <>
+
+ {
+ onEdit(0);
+ }}
+ >
+
+
+
+
+
+ handleLocalEdit("prompt", e.target.value)}
+ className="mb-2 resize-none"
+ placeholder="Prompt"
+ />
+ handleLocalEdit("content", e.target.value)}
+ className="resize-vertical min-h-[100px]"
+ placeholder="Content"
+ />
+
+
+
+ {prompt.id ? "Save" : "Create"}
+
+
+
+ >
+ ) : (
+ <>
+
+
+
+
+
{prompt.prompt}
+ {isPromptPublic(prompt) &&
}
+
+
+ {isPromptPublic(prompt) && (
+
+ This is a built-in prompt and cannot be edited
+
+ )}
+
+
+
{prompt.content}
+
+
+
+
+
+
+
+
+ {!isPromptPublic(prompt) && (
+ onEdit(prompt.id)}>
+ Edit
+
+ )}
+ onDelete(prompt.id)}>
+ Delete
+
+
+
+
+ >
+ )}
+
+ );
+};
diff --git a/web/src/app/chat/input-prompts/PromptCard.tsx b/web/src/app/chat/input-prompts/PromptCard.tsx
new file mode 100644
index 000000000000..09c1faf2c909
--- /dev/null
+++ b/web/src/app/chat/input-prompts/PromptCard.tsx
@@ -0,0 +1,147 @@
+import { SourceChip } from "../input/ChatInputBar";
+
+import { useEffect } from "react";
+import { useState } from "react";
+import { InputPrompt } from "../interfaces";
+import { Button } from "@/components/ui/button";
+import { XIcon } from "@/components/icons/icons";
+import { Textarea } from "@/components/ui/textarea";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from "@/components/ui/tooltip";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { MoreVertical } from "lucide-react";
+
+export const PromptCard = ({
+ prompt,
+ editingPromptId,
+ setEditingPromptId,
+ handleSave,
+ handleDelete,
+ isPromptPublic,
+ handleEdit,
+ fetchInputPrompts,
+}: {
+ prompt: InputPrompt;
+ editingPromptId: number | null;
+ setEditingPromptId: (id: number | null) => void;
+ handleSave: (id: number, prompt: string, content: string) => void;
+ handleDelete: (id: number) => void;
+ isPromptPublic: (prompt: InputPrompt) => boolean;
+ handleEdit: (id: number) => void;
+ fetchInputPrompts: () => void;
+}) => {
+ const isEditing = editingPromptId === prompt.id;
+ const [localPrompt, setLocalPrompt] = useState(prompt.prompt);
+ const [localContent, setLocalContent] = useState(prompt.content);
+
+ // Sync local edits with any prompt changes from outside
+ useEffect(() => {
+ setLocalPrompt(prompt.prompt);
+ setLocalContent(prompt.content);
+ }, [prompt, isEditing]);
+
+ const handleLocalEdit = (field: "prompt" | "content", value: string) => {
+ if (field === "prompt") {
+ setLocalPrompt(value);
+ } else {
+ setLocalContent(value);
+ }
+ };
+
+ const handleSaveLocal = () => {
+ handleSave(prompt.id, localPrompt, localContent);
+ };
+
+ return (
+
+ {isEditing ? (
+ <>
+
+ {
+ setEditingPromptId(null);
+ fetchInputPrompts(); // Revert changes from server
+ }}
+ >
+
+
+
+
+
+ handleLocalEdit("prompt", e.target.value)}
+ className="mb-2 resize-none"
+ placeholder="Prompt"
+ />
+ handleLocalEdit("content", e.target.value)}
+ className="resize-vertical min-h-[100px]"
+ placeholder="Content"
+ />
+
+
+
+ {prompt.id ? "Save" : "Create"}
+
+
+
+ >
+ ) : (
+ <>
+
+
+
+
+
{prompt.prompt}
+ {isPromptPublic(prompt) &&
}
+
+
+ {isPromptPublic(prompt) && (
+
+ This is a built-in prompt and cannot be edited
+
+ )}
+
+
+
{prompt.content}
+
+
+
+
+
+
+
+
+ {!isPromptPublic(prompt) && (
+ handleEdit(prompt.id)}>
+ Edit
+
+ )}
+ handleDelete(prompt.id)}>
+ Delete
+
+
+
+
+ >
+ )}
+
+ );
+};
diff --git a/web/src/app/chat/input/ChatInputBar.tsx b/web/src/app/chat/input/ChatInputBar.tsx
index f8a5c34aa253..358362274949 100644
--- a/web/src/app/chat/input/ChatInputBar.tsx
+++ b/web/src/app/chat/input/ChatInputBar.tsx
@@ -154,7 +154,6 @@ export const SourceChip = ({
gap-x-1
h-6
${onClick ? "cursor-pointer" : ""}
- animate-fade-in-scale
`}
>
{icon}
diff --git a/web/src/app/chat/modal/UserSettingsModal.tsx b/web/src/app/chat/modal/UserSettingsModal.tsx
index 61d7e7d5422c..56dea8219987 100644
--- a/web/src/app/chat/modal/UserSettingsModal.tsx
+++ b/web/src/app/chat/modal/UserSettingsModal.tsx
@@ -40,8 +40,13 @@ export function UserSettingsModal({
onClose: () => void;
defaultModel: string | null;
}) {
- const { refreshUser, user, updateUserAutoScroll, updateUserShortcuts } =
- useUser();
+ const {
+ refreshUser,
+ user,
+ updateUserAutoScroll,
+ updateUserShortcuts,
+ updateUserTemperatureOverrideEnabled,
+ } = useUser();
const containerRef = useRef(null);
const messageRef = useRef(null);
const { theme, setTheme } = useTheme();
@@ -156,11 +161,6 @@ export function UserSettingsModal({
const settings = useContext(SettingsContext);
const autoScroll = settings?.settings?.auto_scroll;
- const checked =
- user?.preferences?.auto_scroll === null
- ? autoScroll
- : user?.preferences?.auto_scroll;
-
const handleChangePassword = async (e: React.FormEvent) => {
e.preventDefault();
if (newPassword !== confirmPassword) {
@@ -288,12 +288,26 @@ export function UserSettingsModal({
Automatically scroll to new content
{
updateUserAutoScroll(checked);
}}
/>
+
+
+
+ Temperature override
+
+ Set the temperature for the LLM
+
+
{
+ updateUserTemperatureOverrideEnabled(checked);
+ }}
+ />
+
Prompt Shortcuts
diff --git a/web/src/components/user/UserProvider.tsx b/web/src/components/user/UserProvider.tsx
index 6f742fa9fdc0..21135b2d6dcc 100644
--- a/web/src/components/user/UserProvider.tsx
+++ b/web/src/components/user/UserProvider.tsx
@@ -13,7 +13,7 @@ interface UserContextType {
isCurator: boolean;
refreshUser: () => Promise;
isCloudSuperuser: boolean;
- updateUserAutoScroll: (autoScroll: boolean | null) => Promise;
+ updateUserAutoScroll: (autoScroll: boolean) => Promise;
updateUserShortcuts: (enabled: boolean) => Promise;
toggleAssistantPinnedStatus: (
currentPinnedAssistantIDs: number[],
@@ -163,7 +163,7 @@ export function UserProvider({
}
};
- const updateUserAutoScroll = async (autoScroll: boolean | null) => {
+ const updateUserAutoScroll = async (autoScroll: boolean) => {
try {
const response = await fetch("/api/auto-scroll", {
method: "PATCH",
diff --git a/web/src/lib/types.ts b/web/src/lib/types.ts
index 733bbfa028c5..7288fe905b3f 100644
--- a/web/src/lib/types.ts
+++ b/web/src/lib/types.ts
@@ -10,7 +10,7 @@ interface UserPreferences {
pinned_assistants?: number[];
default_model: string | null;
recent_assistants: number[];
- auto_scroll: boolean | null;
+ auto_scroll: boolean;
shortcut_enabled: boolean;
temperature_override_enabled: boolean;
}