diff --git a/frontend/src/locales/ar/common.js b/frontend/src/locales/ar/common.js index 26af0974436..dec22f16261 100644 --- a/frontend/src/locales/ar/common.js +++ b/frontend/src/locales/ar/common.js @@ -231,6 +231,16 @@ const TRANSLATIONS = { title: "النداء", description: "النداء التي سيتم استخدامه في مساحة العمل هذه. حدد السياق والتعليمات للذكاء الاصطناعي للاستجابة. يجب عليك تقديم نداء مصمم بعناية حتى يتمكن الذكاء الاصطناعي من إنشاء استجابة دقيقة وذات صلة.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "الرد على رفض وضعية الاستعلام", diff --git a/frontend/src/locales/da/common.js b/frontend/src/locales/da/common.js index e6b421b1097..23c9316ea7a 100644 --- a/frontend/src/locales/da/common.js +++ b/frontend/src/locales/da/common.js @@ -232,6 +232,16 @@ const TRANSLATIONS = { title: "Prompt", description: "Prompten, der vil blive brugt i dette arbejdsområde. Definér konteksten og instruktionerne til, at AI'en kan generere et svar. Du bør levere en omhyggeligt udformet prompt, så AI'en kan generere et relevant og præcist svar.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Afvisningssvar for forespørgsels-tilstand", diff --git a/frontend/src/locales/de/common.js b/frontend/src/locales/de/common.js index a7cae3d3679..40ab0bd978b 100644 --- a/frontend/src/locales/de/common.js +++ b/frontend/src/locales/de/common.js @@ -224,6 +224,16 @@ const TRANSLATIONS = { title: "Prompt", description: "Der Prompt, der in diesem Arbeitsbereich verwendet wird. Definieren Sie den Kontext und die Anweisungen für die KI, um eine Antwort zu generieren. Sie sollten einen sorgfältig formulierten Prompt bereitstellen, damit die KI eine relevante und genaue Antwort generieren kann.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Abfragemodus-Ablehnungsantwort", diff --git a/frontend/src/locales/en/common.js b/frontend/src/locales/en/common.js index ba1fea0d3a3..0246653617e 100644 --- a/frontend/src/locales/en/common.js +++ b/frontend/src/locales/en/common.js @@ -325,9 +325,20 @@ const TRANSLATIONS = { "Anything more than 45 is likely to lead to continuous chat failures depending on message size.", }, prompt: { - title: "Prompt", + title: "System Prompt", description: "The prompt that will be used on this workspace. Define the context and instructions for the AI to generate a response. You should to provide a carefully crafted prompt so the AI can generate a relevant and accurate response.", + history: { + title: "System Prompt History", + clearAll: "Clear All", + noHistory: "No system prompt history available", + restore: "Restore", + delete: "Delete", + deleteConfirm: "Are you sure you want to delete this history item?", + clearAllConfirm: + "Are you sure you want to clear all history? This action cannot be undone.", + expand: "Expand", + }, }, refusal: { title: "Query mode refusal response", diff --git a/frontend/src/locales/es/common.js b/frontend/src/locales/es/common.js index 14a03c3fc1b..f73c58179aa 100644 --- a/frontend/src/locales/es/common.js +++ b/frontend/src/locales/es/common.js @@ -226,6 +226,16 @@ const TRANSLATIONS = { title: "Prompt", description: "El prompt que se utilizará en este espacio de trabajo. Define el contexto y las instrucciones para que la IA genere una respuesta. Debes proporcionar un prompt cuidadosamente elaborado para que la IA pueda generar una respuesta relevante y precisa.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Respuesta de rechazo en modo consulta", diff --git a/frontend/src/locales/fa/common.js b/frontend/src/locales/fa/common.js index d1c9a70775c..effb881874d 100644 --- a/frontend/src/locales/fa/common.js +++ b/frontend/src/locales/fa/common.js @@ -222,6 +222,16 @@ const TRANSLATIONS = { title: "پیش‌متن", description: "پیش‌متنی که در این فضای کاری استفاده خواهد شد. زمینه و دستورالعمل‌ها را برای تولید پاسخ توسط هوش مصنوعی تعریف کنید. باید یک پیش‌متن دقیق ارائه دهید تا هوش مصنوعی بتواند پاسخی مرتبط و دقیق تولید کند.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "پاسخ رد در حالت پرس‌وجو", diff --git a/frontend/src/locales/fr/common.js b/frontend/src/locales/fr/common.js index 4023b0001c8..d3c51c323db 100644 --- a/frontend/src/locales/fr/common.js +++ b/frontend/src/locales/fr/common.js @@ -227,6 +227,16 @@ const TRANSLATIONS = { title: "Invite", description: "L'invite qui sera utilisée sur cet espace de travail. Définissez le contexte et les instructions pour que l'IA génère une réponse. Vous devez fournir une invite soigneusement conçue pour que l'IA puisse générer une réponse pertinente et précise.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Réponse de refus en mode requête", diff --git a/frontend/src/locales/he/common.js b/frontend/src/locales/he/common.js index 2d741444a58..c412330aa40 100644 --- a/frontend/src/locales/he/common.js +++ b/frontend/src/locales/he/common.js @@ -220,6 +220,16 @@ const TRANSLATIONS = { title: "בקשה", description: "הבקשה שתיעשה שימוש בה בסביבת העבודה הזו. הגדר את ההקשר וההוראות עבור ה-AI כדי ליצור תגובה. עליך לספק בקשה מעוצבת בקפידה כדי שה-AI יוכל ליצור תגובה רלוונטית ומדויקת.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "תגובת סירוב במצב שאילתה", diff --git a/frontend/src/locales/it/common.js b/frontend/src/locales/it/common.js index 94c4d2ad548..cb8ecb29c25 100644 --- a/frontend/src/locales/it/common.js +++ b/frontend/src/locales/it/common.js @@ -225,6 +225,16 @@ const TRANSLATIONS = { title: "Prompt", description: "Il prompt che verrà utilizzato in quest'area di lavoro. Definisci il contesto e le istruzioni affinché l'IA generi una risposta. Dovresti fornire un prompt elaborato con cura in modo che l'IA possa generare una risposta pertinente e accurata.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Risposta al rifiuto nella modalità di query", diff --git a/frontend/src/locales/ja/common.js b/frontend/src/locales/ja/common.js index 09a3bf6ff43..2f6bcc71476 100644 --- a/frontend/src/locales/ja/common.js +++ b/frontend/src/locales/ja/common.js @@ -231,6 +231,16 @@ const TRANSLATIONS = { title: "プロンプト", description: "このワークスペースで使用するプロンプトです。AIが適切な応答を生成できるよう、コンテキストや指示を定義してください。", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "クエリモード拒否応答", diff --git a/frontend/src/locales/ko/common.js b/frontend/src/locales/ko/common.js index 947bc196c04..830303df303 100644 --- a/frontend/src/locales/ko/common.js +++ b/frontend/src/locales/ko/common.js @@ -220,6 +220,16 @@ const TRANSLATIONS = { title: "프롬프트", description: "이 워크스페이스에서 사용할 프롬프트입니다. AI가 응답을 생성하기 위해 문맥과 지침을 정의합니다. AI가 질문에 대하여 정확한 응답을 생성할 수 있도록 신중하게 프롬프트를 제공해야 합니다.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "쿼리 모드 거부 응답 메시지", diff --git a/frontend/src/locales/nl/common.js b/frontend/src/locales/nl/common.js index 8d05f90e9fe..7321e743ba4 100644 --- a/frontend/src/locales/nl/common.js +++ b/frontend/src/locales/nl/common.js @@ -224,6 +224,16 @@ const TRANSLATIONS = { title: "Prompt", description: "De prompt die in deze werkruimte zal worden gebruikt. Definieer de context en instructies voor de AI om een reactie te genereren. Je moet een zorgvuldig samengestelde prompt geven zodat de AI een relevante en nauwkeurige reactie kan genereren.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Afwijzingsreactie in Querymodus", diff --git a/frontend/src/locales/pt_BR/common.js b/frontend/src/locales/pt_BR/common.js index 1e9bf3b6f2a..8b7a4503dc7 100644 --- a/frontend/src/locales/pt_BR/common.js +++ b/frontend/src/locales/pt_BR/common.js @@ -231,6 +231,16 @@ const TRANSLATIONS = { title: "Prompt", description: "O prompt que será usado neste workspace. Defina o contexto e as instruções para que a IA gere uma resposta. Você deve fornecer um prompt cuidadosamente elaborado para que a IA possa gerar uma resposta relevante e precisa.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Resposta de Recusa no Modo de Consulta", diff --git a/frontend/src/locales/ru/common.js b/frontend/src/locales/ru/common.js index 429b7c3d4ac..b85502b87e5 100644 --- a/frontend/src/locales/ru/common.js +++ b/frontend/src/locales/ru/common.js @@ -233,6 +233,16 @@ const TRANSLATIONS = { title: "Подсказка", description: "Подсказка, которая будет использоваться в этом рабочем пространстве. Определите контекст и инструкции для AI для создания ответа. Вы должны предоставить тщательно разработанную подсказку, чтобы AI мог генерировать релевантный и точный ответ.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Ответ об отказе в режиме запроса", diff --git a/frontend/src/locales/tr/common.js b/frontend/src/locales/tr/common.js index 72f473d4824..755d1ee46c6 100644 --- a/frontend/src/locales/tr/common.js +++ b/frontend/src/locales/tr/common.js @@ -224,6 +224,16 @@ const TRANSLATIONS = { title: "Komut (Prompt)", description: "Bu çalışma alanında kullanılacak komut. Yapay zekanın yanıt üretmesi için bağlam ve talimatları tanımlayın. Uygun ve doğru yanıtlar almak için özenle hazırlanmış bir komut sağlamalısınız.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Sorgu Modu Ret Yanıtı", diff --git a/frontend/src/locales/vn/common.js b/frontend/src/locales/vn/common.js index 5c35353564b..cfe5497e7bf 100644 --- a/frontend/src/locales/vn/common.js +++ b/frontend/src/locales/vn/common.js @@ -223,6 +223,16 @@ const TRANSLATIONS = { title: "Prompt", description: "The prompt that will be used on this workspace. Define the context and instructions for the AI to generate a response. You should to provide a carefully crafted prompt so the AI can generate a relevant and accurate response.", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "Query mode refusal response", diff --git a/frontend/src/locales/zh/common.js b/frontend/src/locales/zh/common.js index 5d3dcdad77d..07c6a459476 100644 --- a/frontend/src/locales/zh/common.js +++ b/frontend/src/locales/zh/common.js @@ -222,6 +222,16 @@ const TRANSLATIONS = { title: "聊天提示", description: "将在此工作区上使用的提示。定义 AI 生成响应的上下文和指令。你应该提供精心设计的提示,以便人工智能可以生成相关且准确的响应。", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "查询模式拒绝响应", diff --git a/frontend/src/locales/zh_TW/common.js b/frontend/src/locales/zh_TW/common.js index 6b6bdfeeefe..3470d3770d9 100644 --- a/frontend/src/locales/zh_TW/common.js +++ b/frontend/src/locales/zh_TW/common.js @@ -221,6 +221,16 @@ const TRANSLATIONS = { title: "提示詞", description: "將在此工作區中使用的提示詞。定義 AI 產生回應的上下文和指示。您應該提供精心設計的提示詞,以便 AI 可以產生相關且準確的回應。", + history: { + title: null, + clearAll: null, + noHistory: null, + restore: null, + delete: null, + deleteConfirm: null, + clearAllConfirm: null, + expand: null, + }, }, refusal: { title: "查詢模式拒絕回應", diff --git a/frontend/src/models/promptHistory.js b/frontend/src/models/promptHistory.js new file mode 100644 index 00000000000..fdabb795a68 --- /dev/null +++ b/frontend/src/models/promptHistory.js @@ -0,0 +1,84 @@ +import { API_BASE } from "@/utils/constants"; +import { baseHeaders } from "@/utils/request"; + +/** + * @typedef {Object} PromptHistory + * @property {number} id - The ID of the prompt history entry + * @property {number} workspaceId - The ID of the workspace + * @property {string} prompt - The prompt text + * @property {number|null} modifiedBy - The ID of the user who modified the prompt + * @property {Date} modifiedAt - The date when the prompt was modified + * @property {Object|null} user - The user who modified the prompt + */ + +const PromptHistory = { + /** + * Get all prompt history for a workspace + * @param {number} workspaceId - The ID of the workspace + * @returns {Promise} - An array of prompt history entries + */ + forWorkspace: async function (workspaceId) { + try { + return await fetch( + `${API_BASE}/workspace/${workspaceId}/prompt-history`, + { + method: "GET", + headers: baseHeaders(), + } + ) + .then((res) => res.json()) + .then((res) => res.history || []) + .catch((error) => { + console.error("Error fetching prompt history:", error); + return []; + }); + } catch (error) { + console.error("Error fetching prompt history:", error); + return []; + } + }, + + /** + * Delete all prompt history for a workspace + * @param {number} workspaceId - The ID of the workspace + * @returns {Promise<{success: boolean, error: string}>} - A promise that resolves to an object containing a success flag and an error message + */ + clearAll: async function (workspaceId) { + try { + return await fetch( + `${API_BASE}/workspace/${workspaceId}/prompt-history`, + { + method: "DELETE", + headers: baseHeaders(), + } + ) + .then((res) => res.json()) + .catch((error) => { + console.error("Error clearing prompt history:", error); + return { success: false, error }; + }); + } catch (error) { + console.error("Error clearing prompt history:", error); + return { success: false, error }; + } + }, + + delete: async function (id) { + try { + return await fetch(`${API_BASE}/workspace/prompt-history/${id}`, { + method: "DELETE", + headers: baseHeaders(), + }) + .then((res) => res.json()) + .catch((error) => { + console.error("Error deleting prompt history:", error); + return { success: false, error }; + }); + } catch (error) { + console.error("Error deleting prompt history:", error); + return { success: false, error }; + } + }, +}; + +export default PromptHistory; diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/ChatPromptHistory/PromptHistoryItem/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/ChatPromptHistory/PromptHistoryItem/index.jsx new file mode 100644 index 00000000000..34a5c7644aa --- /dev/null +++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/ChatPromptHistory/PromptHistoryItem/index.jsx @@ -0,0 +1,121 @@ +import { DotsThreeVertical } from "@phosphor-icons/react"; +import moment from "moment"; +import { useRef, useState, useEffect } from "react"; +import PromptHistory from "@/models/promptHistory"; +import truncate from "truncate"; +import { useTranslation } from "react-i18next"; +const MAX_PROMPT_LENGTH = 200; // chars + +export default function PromptHistoryItem({ + id, + prompt, + modifiedAt, + user, + onRestore, + setHistory, +}) { + const { t } = useTranslation(); + const [showMenu, setShowMenu] = useState(false); + const menuRef = useRef(null); + const menuButtonRef = useRef(null); + const [expanded, setExpanded] = useState(false); + + const deleteHistory = async (id) => { + if (window.confirm(t("chat.prompt.history.deleteConfirm"))) { + const { success } = await PromptHistory.delete(id); + if (success) { + setHistory((prevHistory) => + prevHistory.filter((item) => item.id !== id) + ); + } + } + }; + + useEffect(() => { + const handleClickOutside = (event) => { + if ( + showMenu && + !menuRef.current.contains(event.target) && + !menuButtonRef.current.contains(event.target) + ) { + setShowMenu(false); + } + }; + document.addEventListener("mousedown", handleClickOutside); + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [showMenu]); + + return ( +
+
+
+ {user && ( + <> + {user.username}{" "} + + + )} + + {moment(modifiedAt).fromNow()} + +
+
+ +
+ + {showMenu && ( +
+ +
+ )} +
+
+
+
+
+ {prompt.length > MAX_PROMPT_LENGTH && !expanded ? ( + <> + {truncate(prompt, MAX_PROMPT_LENGTH)}{" "} + + + ) : ( + prompt + )} +
+
+
+ ); +} diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/ChatPromptHistory/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/ChatPromptHistory/index.jsx new file mode 100644 index 00000000000..0c23f70cb2a --- /dev/null +++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/ChatPromptHistory/index.jsx @@ -0,0 +1,116 @@ +import { useEffect, useState, forwardRef } from "react"; +import PromptHistory from "@/models/promptHistory"; +import { X } from "@phosphor-icons/react"; +import PromptHistoryItem from "./PromptHistoryItem"; +import * as Skeleton from "react-loading-skeleton"; +import "react-loading-skeleton/dist/skeleton.css"; +import { useTranslation } from "react-i18next"; + +export default forwardRef(function ChatPromptHistory( + { show, workspaceSlug, onRestore, onClose }, + ref +) { + const { t } = useTranslation(); + const [history, setHistory] = useState([]); + const [loading, setLoading] = useState(true); + + function loadHistory() { + if (!workspaceSlug) return; + setLoading(true); + PromptHistory.forWorkspace(workspaceSlug) + .then((historyData) => { + setHistory(historyData); + }) + .catch((error) => { + console.error(error); + }) + .finally(() => { + setLoading(false); + }); + } + + function handleClearAll() { + if (!workspaceSlug) return; + if (window.confirm(t("chat.prompt.history.clearAllConfirm"))) { + PromptHistory.clearAll(workspaceSlug) + .then(({ success }) => { + if (success) setHistory([]); + }) + .catch((error) => { + console.error(error); + }); + } + } + + useEffect(() => { + if (show && workspaceSlug) loadHistory(); + }, [show, workspaceSlug]); + + return ( +
+
+
+ {t("chat.prompt.history.title")} +
+
+ {history.length > 0 && ( + + )} + +
+
+
+ {loading ? ( + + ) : history.length === 0 ? ( +
+ {t("chat.prompt.history.noHistory")} +
+ ) : ( + history.map((item) => ( + onRestore(item.prompt)} + setHistory={setHistory} + /> + )) + )} +
+
+ ); +}); + +function LoaderSkeleton() { + const highlightColor = "var(--theme-bg-primary)"; + const baseColor = "var(--theme-bg-secondary)"; + return ( + + ); +} diff --git a/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/index.jsx b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/index.jsx index e6b54fe5323..4e4fe04024b 100644 --- a/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/index.jsx +++ b/frontend/src/pages/WorkspaceSettings/ChatSettings/ChatPromptSettings/index.jsx @@ -5,15 +5,30 @@ import SystemPromptVariable from "@/models/systemPromptVariable"; import Highlighter from "react-highlight-words"; import { Link, useSearchParams } from "react-router-dom"; import paths from "@/utils/paths"; +import ChatPromptHistory from "./ChatPromptHistory"; + +// TODO: Move to backend and have user-language sensitive default prompt +const DEFAULT_PROMPT = + "Given the following conversation, relevant context, and a follow up question, reply with an answer to the current question the user is asking. Return only your response to the question given the above information following the users instructions as needed."; export default function ChatPromptSettings({ workspace, setHasChanges }) { const { t } = useTranslation(); const [availableVariables, setAvailableVariables] = useState([]); const [prompt, setPrompt] = useState(chatPrompt(workspace)); const [isEditing, setIsEditing] = useState(false); + const [showPromptHistory, setShowPromptHistory] = useState(false); const promptRef = useRef(null); + const promptHistoryRef = useRef(null); + const historyButtonRef = useRef(null); const [searchParams] = useSearchParams(); + const handleRestore = (prompt) => { + setPrompt(prompt); + setShowPromptHistory(false); + setHasChanges(true); + // TODO: Autosave on restore + }; + useEffect(() => { async function setupVariableHighlighting() { const { variables } = await SystemPromptVariable.getAll(); @@ -33,104 +48,155 @@ export default function ChatPromptSettings({ workspace, setHasChanges }) { } }, [isEditing]); + useEffect(() => { + const handleClickOutside = (event) => { + if ( + promptHistoryRef.current && + !promptHistoryRef.current.contains(event.target) && + historyButtonRef.current && + !historyButtonRef.current.contains(event.target) + ) { + setShowPromptHistory(false); + } + }; + document.addEventListener("mousedown", handleClickOutside); + + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, []); + return ( -
-
- -

- {t("chat.prompt.description")} -

-

- You can insert{" "} - - prompt variables - {" "} - like:{" "} - {availableVariables.slice(0, 3).map((v, i) => ( - - - {`{${v.key}}`} - - {i < availableVariables.length - 1 && ", "} - - ))} - {availableVariables.length > 3 && ( + <> + { + setShowPromptHistory(false); + }} + /> +

+
+
+ +
+

+ {t("chat.prompt.description")} +

+

+ You can insert{" "} - +{availableVariables.length - 3} more... - - )} -

-
+ prompt variables + {" "} + like:{" "} + {availableVariables.slice(0, 3).map((v, i) => ( + + + {`{${v.key}}`} + + {i < availableVariables.length - 1 && ", "} + + ))} + {availableVariables.length > 3 && ( + + +{availableVariables.length - 3} more... + + )} +

+
- - -
- - Given the following conversation, relevant context, and a follow up - question, reply with an answer to the current question the user is - asking. Return only your response to the question given the above - information following the users instructions as needed. - - {isEditing ? ( -