From 61e4bc6b171b1f02a2b1454f5da8afa9196caf6e Mon Sep 17 00:00:00 2001 From: JzoNg Date: Sun, 12 Oct 2025 13:12:50 +0800 Subject: [PATCH] memory in web app --- .../base/chat/chat-with-history/context.tsx | 13 ++ .../base/chat/chat-with-history/hooks.tsx | 65 ++++++++++ .../base/chat/chat-with-history/index.tsx | 42 ++++++- .../memory/card/edit-modal.tsx | 33 +++-- .../chat-with-history/memory/card/index.tsx | 90 ++++++++++---- .../memory/card/operation.tsx | 13 +- .../chat/chat-with-history/memory/index.tsx | 62 +++++++--- .../chat/chat-with-history/memory/mock.ts | 87 +++++++++++-- .../chat/chat-with-history/memory/type.ts | 6 - .../base/chat/embedded-chatbot/index.tsx | 20 +-- .../memory/card/edit-modal.tsx | 117 ------------------ .../embedded-chatbot/memory/card/index.tsx | 81 ------------ .../memory/card/operation.tsx | 79 ------------ .../chat/embedded-chatbot/memory/index.tsx | 54 -------- .../base/chat/embedded-chatbot/memory/mock.ts | 29 ----- .../base/chat/embedded-chatbot/memory/type.ts | 6 - web/app/components/base/chat/types.ts | 33 +++++ web/i18n/en-US/share.ts | 1 + web/i18n/zh-Hans/share.ts | 1 + web/service/share.ts | 37 +++++- 20 files changed, 420 insertions(+), 449 deletions(-) delete mode 100644 web/app/components/base/chat/chat-with-history/memory/type.ts delete mode 100644 web/app/components/base/chat/embedded-chatbot/memory/card/edit-modal.tsx delete mode 100644 web/app/components/base/chat/embedded-chatbot/memory/card/index.tsx delete mode 100644 web/app/components/base/chat/embedded-chatbot/memory/card/operation.tsx delete mode 100644 web/app/components/base/chat/embedded-chatbot/memory/index.tsx delete mode 100644 web/app/components/base/chat/embedded-chatbot/memory/mock.ts delete mode 100644 web/app/components/base/chat/embedded-chatbot/memory/type.ts diff --git a/web/app/components/base/chat/chat-with-history/context.tsx b/web/app/components/base/chat/chat-with-history/context.tsx index 5d4f9ec358..b6f79a8c0a 100644 --- a/web/app/components/base/chat/chat-with-history/context.tsx +++ b/web/app/components/base/chat/chat-with-history/context.tsx @@ -7,6 +7,7 @@ import type { ChatConfig, ChatItemInTree, Feedback, + Memory, } from '../types' import type { ThemeBuilder } from '../embedded-chatbot/theme/theme-context' import type { @@ -62,6 +63,12 @@ export type ChatWithHistoryContextValue = { } showChatMemory?: boolean setShowChatMemory: (state: boolean) => void + memoryList: Memory[] + clearAllMemory: () => void + updateMemory: (memory: Memory, content: string) => void + resetDefault: (memory: Memory) => void + clearAllUpdateVersion: (memory: Memory) => void + switchMemoryVersion: (memory: Memory, version: string) => void } export const ChatWithHistoryContext = createContext({ @@ -99,5 +106,11 @@ export const ChatWithHistoryContext = createContext initUserVariables: {}, showChatMemory: false, setShowChatMemory: noop, + memoryList: [], + clearAllMemory: noop, + updateMemory: noop, + resetDefault: noop, + clearAllUpdateVersion: noop, + switchMemoryVersion: noop, }) export const useChatWithHistoryContext = () => useContext(ChatWithHistoryContext) diff --git a/web/app/components/base/chat/chat-with-history/hooks.tsx b/web/app/components/base/chat/chat-with-history/hooks.tsx index 144f3aeb4d..38a7ab8523 100644 --- a/web/app/components/base/chat/chat-with-history/hooks.tsx +++ b/web/app/components/base/chat/chat-with-history/hooks.tsx @@ -21,8 +21,11 @@ import { addFileInfos, sortAgentSorts } from '../../../tools/utils' import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils' import { delConversation, + deleteMemory, + editMemory, fetchChatList, fetchConversations, + fetchMemories, generationConversationName, pinConversation, renameConversation, @@ -41,6 +44,9 @@ import { InputVarType } from '@/app/components/workflow/types' import { TransferMethod } from '@/types/app' import { noop } from 'lodash-es' import { useWebAppStore } from '@/context/web-app-context' +import type { Memory } from '@/app/components/base/chat/types' + +import { mockMemoryList } from '@/app/components/base/chat/chat-with-history/memory/mock' function getFormattedChatList(messages: any[]) { const newChatList: ChatItem[] = [] @@ -527,6 +533,59 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => { }, [isInstalledApp, appId, t, notify]) const [showChatMemory, setShowChatMemory] = useState(false) + const [memoryList, setMemoryList] = useState(mockMemoryList) + + const getMemoryList = useCallback(async (currentConversationId: string) => { + const memories = await fetchMemories(currentConversationId, '', '', isInstalledApp, appId) + setMemoryList(memories) + }, [isInstalledApp, appId]) + + const clearAllMemory = useCallback(async () => { + await deleteMemory('', isInstalledApp, appId) + notify({ type: 'success', message: t('common.api.success') }) + getMemoryList(currentConversationId) + }, [currentConversationId, getMemoryList]) + + const resetDefault = useCallback(async (memory: Memory) => { + try { + await editMemory(memory.spec.id, memory.spec.template, isInstalledApp, appId) + getMemoryList(currentConversationId) + } + catch (error) { + console.error('Failed to reset memory:', error) + } + }, [currentConversationId, getMemoryList, isInstalledApp, appId]) + + const clearAllUpdateVersion = useCallback(async (memory: Memory) => { + await deleteMemory(memory.spec.id, isInstalledApp, appId) + notify({ type: 'success', message: t('common.api.success') }) + getMemoryList(currentConversationId) + }, [currentConversationId, getMemoryList]) + + const switchMemoryVersion = useCallback(async (memory: Memory, version: string) => { + const memories = await fetchMemories(currentConversationId, memory.spec.id, version, isInstalledApp, appId) + const newMemory = memories[0] + const newList = produce(memoryList, (draft) => { + const index = draft.findIndex(item => item.spec.id === memory.spec.id) + if (index !== -1) + draft[index] = newMemory + }) + setMemoryList(newList) + }, [memoryList, currentConversationId, isInstalledApp, appId]) + + const updateMemory = useCallback(async (memory: Memory, content: string) => { + try { + await editMemory(memory.spec.id, content, isInstalledApp, appId) + getMemoryList(currentConversationId) + } + catch (error) { + console.error('Failed to reset memory:', error) + } + }, [getMemoryList, currentConversationId, isInstalledApp, appId]) + + useEffect(() => { + getMemoryList(currentConversationId) + }, [currentConversationId, getMemoryList]) return { isInstalledApp, @@ -576,5 +635,11 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => { initUserVariables, showChatMemory, setShowChatMemory, + memoryList, + clearAllMemory, + updateMemory, + resetDefault, + clearAllUpdateVersion, + switchMemoryVersion, } } diff --git a/web/app/components/base/chat/chat-with-history/index.tsx b/web/app/components/base/chat/chat-with-history/index.tsx index 0cd3c6174f..055dfb331f 100644 --- a/web/app/components/base/chat/chat-with-history/index.tsx +++ b/web/app/components/base/chat/chat-with-history/index.tsx @@ -39,6 +39,12 @@ const ChatWithHistory: FC = ({ sidebarCollapseState, showChatMemory, setShowChatMemory, + memoryList, + clearAllMemory, + updateMemory, + resetDefault, + clearAllUpdateVersion, + switchMemoryVersion, } = useChatWithHistoryContext() const isSidebarCollapsed = sidebarCollapseState const customConfig = appData?.custom_config @@ -101,14 +107,34 @@ const ChatWithHistory: FC = ({ )} {!isMobile && ( - + )} {isMobile && showChatMemory && (
setShowChatMemory(false)} >
e.stopPropagation()}> - +
)} @@ -169,6 +195,12 @@ const ChatWithHistoryWrap: FC = ({ initUserVariables, showChatMemory, setShowChatMemory, + memoryList, + clearAllMemory, + updateMemory, + resetDefault, + clearAllUpdateVersion, + switchMemoryVersion, } = useChatWithHistory(installedAppInfo) return ( @@ -214,6 +246,12 @@ const ChatWithHistoryWrap: FC = ({ initUserVariables, showChatMemory, setShowChatMemory, + memoryList, + clearAllMemory, + updateMemory, + resetDefault, + clearAllUpdateVersion, + switchMemoryVersion, }}> diff --git a/web/app/components/base/chat/chat-with-history/memory/card/edit-modal.tsx b/web/app/components/base/chat/chat-with-history/memory/card/edit-modal.tsx index b3ba52f0e3..a745fed5e5 100644 --- a/web/app/components/base/chat/chat-with-history/memory/card/edit-modal.tsx +++ b/web/app/components/base/chat/chat-with-history/memory/card/edit-modal.tsx @@ -1,5 +1,5 @@ 'use client' -import React from 'react' +import React, { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { RiCloseLine } from '@remixicon/react' import { Memory } from '@/app/components/base/icons/src/vender/line/others' @@ -10,14 +10,14 @@ import Button from '@/app/components/base/button' import Textarea from '@/app/components/base/textarea' import Divider from '@/app/components/base/divider' import Toast from '@/app/components/base/toast' -import type { MemoryItem } from '../type' +import type { Memory as MemoryItem } from '@/app/components/base/chat/types' import { noop } from 'lodash-es' import cn from '@/utils/classnames' type Props = { memory: MemoryItem show: boolean - onConfirm: (info: MemoryItem) => Promise + onConfirm: (info: MemoryItem, content: string) => Promise onHide: () => void isMobile?: boolean } @@ -30,14 +30,25 @@ const MemoryEditModal = ({ isMobile, }: Props) => { const { t } = useTranslation() - const [content, setContent] = React.useState(memory.content) + const [content, setContent] = React.useState(memory.value) + + const versionTag = useMemo(() => { + const res = `${t('share.chat.memory.updateVersion.update')} ${memory.version}` + if (memory.edited_by_user) + return `${res} · ${t('share.chat.memory.updateVersion.edited')}` + return res + }, [memory.version, t]) + + const reset = () => { + setContent(memory.value) + } const submit = () => { if (!content.trim()) { Toast.notify({ type: 'error', message: 'content is required' }) return } - onConfirm({ ...memory, content }) + onConfirm(memory, content) onHide() } @@ -56,8 +67,8 @@ const MemoryEditModal = ({
{t('share.chat.memory.editTitle')}
-
{memory.name}
- +
{memory.spec.name}
+ {memory.version > 1 && }
@@ -71,7 +82,7 @@ const MemoryEditModal = ({ - +
@@ -93,8 +104,8 @@ const MemoryEditModal = ({
{t('share.chat.memory.editTitle')}
-
{memory.name}
- +
{memory.spec.name}
+ {memory.version > 1 && }
@@ -108,7 +119,7 @@ const MemoryEditModal = ({ - +
) diff --git a/web/app/components/base/chat/chat-with-history/memory/card/index.tsx b/web/app/components/base/chat/chat-with-history/memory/card/index.tsx index a6ac25081a..970597b57a 100644 --- a/web/app/components/base/chat/chat-with-history/memory/card/index.tsx +++ b/web/app/components/base/chat/chat-with-history/memory/card/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { RiArrowDownSLine, @@ -10,53 +10,100 @@ import Badge from '@/app/components/base/badge' import Indicator from '@/app/components/header/indicator' import Operation from './operation' import MemoryEditModal from './edit-modal' -import type { MemoryItem } from '../type' +import type { Memory as MemoryItem } from '@/app/components/base/chat/types' import cn from '@/utils/classnames' type Props = { - memory: MemoryItem isMobile?: boolean + memory: MemoryItem + updateMemory: (memory: MemoryItem, content: string) => void + resetDefault: (memory: MemoryItem) => void + clearAllUpdateVersion: (memory: MemoryItem) => void + switchMemoryVersion: (memory: MemoryItem, version: string) => void } -const MemoryCard: React.FC = ({ memory, isMobile }) => { +const MemoryCard: React.FC = ({ + isMobile, + memory, + updateMemory, + resetDefault, + clearAllUpdateVersion, + switchMemoryVersion, +}) => { const { t } = useTranslation() const [isHovering, setIsHovering] = React.useState(false) const [showEditModal, setShowEditModal] = React.useState(false) + const versionTag = useMemo(() => { + const res = `${t('share.chat.memory.updateVersion.update')} ${memory.version}` + if (memory.edited_by_user) + return `${res} · ${t('share.chat.memory.updateVersion.edited')}` + return res + }, [memory.version, t]) + + const isLatest = useMemo(() => { + if (memory.conversation_metadata) + return memory.conversation_metadata.visible_count === memory.spec.preserved_turns + + return true + }, [memory]) + + const waitMergeCount = useMemo(() => { + if (memory.conversation_metadata) + return memory.conversation_metadata.visible_count - memory.spec.preserved_turns + + return 0 + }, [memory]) + + const prevVersion = () => { + if (memory.version > 1) + switchMemoryVersion(memory, (memory.version - 1).toString()) + } + + const nextVersion = () => { + switchMemoryVersion(memory, (memory.version + 1).toString()) + } + return ( <>
setIsHovering(true)} onMouseLeave={() => setIsHovering(false)} > -
+
-
{memory.name}
- +
{memory.spec.name}
+ {memory.version > 1 && }
{isHovering && ( -
- - - { - setShowEditModal(true) - setIsHovering(false) - }} /> +
+ + + { + setShowEditModal(true) + setIsHovering(false) + }} + resetDefault={resetDefault} + clearAllUpdateVersion={clearAllUpdateVersion} + switchMemoryVersion={switchMemoryVersion} + />
)}
-
{memory.content}
- {memory.status === 'latest' && ( +
{memory.value}
+ {isLatest && (
{t('share.chat.memory.latestVersion')}
)} - {memory.status === 'needUpdate' && ( + {!isLatest && (
-
{t('share.chat.memory.notLatestVersion', { num: memory.mergeCount })}
+
{t('share.chat.memory.notLatestVersion', { num: waitMergeCount })}
)} @@ -66,9 +113,8 @@ const MemoryCard: React.FC = ({ memory, isMobile }) => { isMobile={isMobile} show={showEditModal} memory={memory} - onConfirm={async (info) => { - // Handle confirm logic here - console.log('Memory updated:', info) + onConfirm={async (info, content) => { + await updateMemory(info, content) setShowEditModal(false) }} onHide={() => setShowEditModal(false)} diff --git a/web/app/components/base/chat/chat-with-history/memory/card/operation.tsx b/web/app/components/base/chat/chat-with-history/memory/card/operation.tsx index 7ac2876cca..b50ab79a98 100644 --- a/web/app/components/base/chat/chat-with-history/memory/card/operation.tsx +++ b/web/app/components/base/chat/chat-with-history/memory/card/operation.tsx @@ -10,14 +10,23 @@ import { PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' import Divider from '@/app/components/base/divider' +import type { Memory } from '@/app/components/base/chat/types' import cn from '@/utils/classnames' type Props = { + memory: Memory onEdit: () => void + resetDefault: (memory: Memory) => void + clearAllUpdateVersion: (memory: Memory) => void + switchMemoryVersion: (memory: Memory, version: string) => void } const OperationDropdown: FC = ({ + memory, onEdit, + resetDefault, + clearAllUpdateVersion, + switchMemoryVersion, }) => { const { t } = useTranslation() const [open, doSetOpen] = useState(false) @@ -52,8 +61,8 @@ const OperationDropdown: FC = ({
{t('share.chat.memory.operations.edit')}
-
{t('share.chat.memory.operations.reset')}
-
{t('share.chat.memory.operations.clear')}
+
resetDefault(memory)}>{t('share.chat.memory.operations.reset')}
+
clearAllUpdateVersion(memory)}>{t('share.chat.memory.operations.clear')}
diff --git a/web/app/components/base/chat/chat-with-history/memory/index.tsx b/web/app/components/base/chat/chat-with-history/memory/index.tsx index b45e3c2a95..a3ddda30ba 100644 --- a/web/app/components/base/chat/chat-with-history/memory/index.tsx +++ b/web/app/components/base/chat/chat-with-history/memory/index.tsx @@ -6,29 +6,40 @@ import { } from '@remixicon/react' import ActionButton from '@/app/components/base/action-button' import Button from '@/app/components/base/button' -import { - useChatWithHistoryContext, -} from '../context' import MemoryCard from './card' import cn from '@/utils/classnames' -import { mockMemoryList } from './mock' +import type { Memory } from '@/app/components/base/chat/types' type Props = { + isMobile?: boolean showChatMemory?: boolean + setShowChatMemory: (show: boolean) => void + memoryList: Memory[] + clearAllMemory: () => void + updateMemory: (memory: Memory, content: string) => void + resetDefault: (memory: Memory) => void + clearAllUpdateVersion: (memory: Memory) => void + switchMemoryVersion: (memory: Memory, version: string) => void } -const MemoryPanel: React.FC = ({ showChatMemory }) => { +const MemoryPanel: React.FC = ({ + isMobile, + showChatMemory, + setShowChatMemory, + memoryList, + clearAllMemory, + updateMemory, + resetDefault, + clearAllUpdateVersion, + switchMemoryVersion, +}) => { const { t } = useTranslation() - const { - isMobile, - setShowChatMemory, - } = useChatWithHistoryContext() return (
{t('share.chat.memory.title')}
@@ -37,15 +48,30 @@ const MemoryPanel: React.FC = ({ showChatMemory }) => {
- {mockMemoryList.map(memory => ( - + {memoryList.map(memory => ( + ))} -
- -
+ {memoryList.length > 0 && ( +
+ +
+ )} + {memoryList.length === 0 && ( +
+ {t('share.chat.memory.empty')} +
+ )}
) diff --git a/web/app/components/base/chat/chat-with-history/memory/mock.ts b/web/app/components/base/chat/chat-with-history/memory/mock.ts index 278da9ee07..0a16f66a81 100644 --- a/web/app/components/base/chat/chat-with-history/memory/mock.ts +++ b/web/app/components/base/chat/chat-with-history/memory/mock.ts @@ -1,29 +1,96 @@ -import type { MemoryItem } from './type' +import type { Memory as MemoryItem } from '@/app/components/base/chat/types' + export const mockMemoryList: MemoryItem[] = [ { - name: 'learning_companion', - content: `Learning Goal: [What you\'re studying] + tenant_id: 'user-tenant-id', + value: `Learning Goal: [What you\'re studying] Current Level: [Beginner/Intermediate/Advanced] Learning Style: [Visual, hands-on, theoretical, etc.] Progress: [Topics mastered, current focus] Preferred Pace: [Fast/moderate/slow explanations] Background: [Relevant experience or education] Time Constraints: [Available study time]`, + app_id: 'user-app-id', + conversation_id: '', + version: 1, + edited_by_user: false, + conversation_metadata: { + type: 'mutable_visible_window', + visible_count: 5, + }, + spec: { + id: 'learning_companion', + name: 'Learning Companion', + description: 'A companion to help with learning goals', + template: 'no zuo no die why you try', // default value + instruction: 'enjoy yourself', + scope: 'app', // app or node + term: 'session', // session or persistent + strategy: 'on_turns', + update_turns: 3, + preserved_turns: 5, + schedule_mode: 'sync', // sync or async + end_user_visible: true, + end_user_editable: true, + }, }, { - name: 'research_partner', - content: `Research Topic: [Your research topic] + tenant_id: 'user-tenant-id', + value: `Research Topic: [Your research topic] Current Progress: [Literature review, experiments, etc.] Challenges: [What you\'re struggling with] Goals: [Short-term and long-term research goals]`, - status: 'latest', + app_id: 'user-app-id', + conversation_id: '', + version: 1, + edited_by_user: false, + conversation_metadata: { + type: 'mutable_visible_window', + visible_count: 5, + }, + spec: { + id: 'research_partner', + name: 'research_partner', + description: 'A companion to help with research goals', + template: 'no zuo no die why you try', // default value + instruction: 'enjoy yourself', + scope: 'app', // app or node + term: 'session', // session or persistent + strategy: 'on_turns', + update_turns: 3, + preserved_turns: 3, + schedule_mode: 'sync', // sync or async + end_user_visible: true, + end_user_editable: false, + }, }, { - name: 'code_partner', - content: `Code Context: [Brief description of the codebase] + tenant_id: 'user-tenant-id', + value: `Code Context: [Brief description of the codebase] Current Issues: [Bugs, technical debt, etc.] Goals: [Features to implement, improvements to make]`, - status: 'needUpdate', - mergeCount: 5, + app_id: 'user-app-id', + conversation_id: '', + version: 3, + edited_by_user: true, + conversation_metadata: { + type: 'mutable_visible_window', + visible_count: 5, + }, + spec: { + id: 'code_partner', + name: 'code_partner', + description: 'A companion to help with code-related tasks', + template: 'no zuo no die why you try', // default value + instruction: 'enjoy yourself', + scope: 'app', // app or node + term: 'session', // session or persistent + strategy: 'on_turns', + update_turns: 3, + preserved_turns: 5, + schedule_mode: 'sync', // sync or async + end_user_visible: true, + end_user_editable: true, + }, }, ] diff --git a/web/app/components/base/chat/chat-with-history/memory/type.ts b/web/app/components/base/chat/chat-with-history/memory/type.ts deleted file mode 100644 index 49ea32aed3..0000000000 --- a/web/app/components/base/chat/chat-with-history/memory/type.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type MemoryItem = { - name: string; - content: string; - status?: 'latest' | 'needUpdate'; - mergeCount?: number; -} diff --git a/web/app/components/base/chat/embedded-chatbot/index.tsx b/web/app/components/base/chat/embedded-chatbot/index.tsx index f02eec0d4c..f6d0838b15 100644 --- a/web/app/components/base/chat/embedded-chatbot/index.tsx +++ b/web/app/components/base/chat/embedded-chatbot/index.tsx @@ -16,7 +16,7 @@ import Loading from '@/app/components/base/loading' import LogoHeader from '@/app/components/base/logo/logo-embedded-chat-header' import Header from '@/app/components/base/chat/embedded-chatbot/header' import ChatWrapper from '@/app/components/base/chat/embedded-chatbot/chat-wrapper' -import MemoryPanel from './memory' +import MemoryPanel from '@/app/components/base/chat/chat-with-history/memory' import DifyLogo from '@/app/components/base/logo/dify-logo' import cn from '@/utils/classnames' import useDocumentTitle from '@/hooks/use-document-title' @@ -94,14 +94,18 @@ const Chatbot = () => {
)} {showChatMemory && ( -
setShowChatMemory(false)} - > -
e.stopPropagation()}> - -
+
setShowChatMemory(false)} + > +
e.stopPropagation()}> +
- )} +
+ )}
) } diff --git a/web/app/components/base/chat/embedded-chatbot/memory/card/edit-modal.tsx b/web/app/components/base/chat/embedded-chatbot/memory/card/edit-modal.tsx deleted file mode 100644 index b3ba52f0e3..0000000000 --- a/web/app/components/base/chat/embedded-chatbot/memory/card/edit-modal.tsx +++ /dev/null @@ -1,117 +0,0 @@ -'use client' -import React from 'react' -import { useTranslation } from 'react-i18next' -import { RiCloseLine } from '@remixicon/react' -import { Memory } from '@/app/components/base/icons/src/vender/line/others' -import Modal from '@/app/components/base/modal' -import ActionButton from '@/app/components/base/action-button' -import Badge from '@/app/components/base/badge' -import Button from '@/app/components/base/button' -import Textarea from '@/app/components/base/textarea' -import Divider from '@/app/components/base/divider' -import Toast from '@/app/components/base/toast' -import type { MemoryItem } from '../type' -import { noop } from 'lodash-es' -import cn from '@/utils/classnames' - -type Props = { - memory: MemoryItem - show: boolean - onConfirm: (info: MemoryItem) => Promise - onHide: () => void - isMobile?: boolean -} - -const MemoryEditModal = ({ - memory, - show = false, - onConfirm, - onHide, - isMobile, -}: Props) => { - const { t } = useTranslation() - const [content, setContent] = React.useState(memory.content) - - const submit = () => { - if (!content.trim()) { - Toast.notify({ type: 'error', message: 'content is required' }) - return - } - onConfirm({ ...memory, content }) - onHide() - } - - if (isMobile) { - return ( -
-
e.stopPropagation()}> -
- - - -
-
-
{t('share.chat.memory.editTitle')}
-
- -
{memory.name}
- -
-
-
-