fix(web): ai prompt editor update
This commit is contained in:
@@ -1144,6 +1144,8 @@ export const en = {
|
||||
merge: 'Complete Aggregation',
|
||||
vote: 'Key Information Extraction',
|
||||
priority: 'Structured Integration',
|
||||
addTool: 'Add Tool',
|
||||
tool: 'Tool',
|
||||
},
|
||||
userMemory: {
|
||||
userMemory: 'User Memory',
|
||||
@@ -1201,6 +1203,7 @@ export const en = {
|
||||
IMPLICIT_MEMORY: 'Implicit Memory',
|
||||
EMOTIONAL_MEMORY: 'Emotional Memory',
|
||||
EPISODIC_MEMORY: 'Episodic Memory',
|
||||
FORGETTING_MANAGEMENT: 'Forgetting Management',
|
||||
|
||||
endUserProfile: 'Core Profile',
|
||||
editEndUserProfile: 'Edit',
|
||||
@@ -1833,6 +1836,7 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
|
||||
status_code: 'Status Code',
|
||||
max_attempts: 'Max Retry Attempts',
|
||||
retry_interval: 'Retry Interval',
|
||||
errorBranch: 'Error Branch',
|
||||
},
|
||||
'jinja-render': {
|
||||
template: 'Code',
|
||||
|
||||
@@ -633,6 +633,8 @@ export const zh = {
|
||||
merge: '完整汇总',
|
||||
vote: '关键信息提取',
|
||||
priority: '结构化整合',
|
||||
addTool: '添加工具',
|
||||
tool: '工具',
|
||||
},
|
||||
// 角色管理相关翻译
|
||||
role: {
|
||||
@@ -1280,6 +1282,7 @@ export const zh = {
|
||||
IMPLICIT_MEMORY: '隐性记忆',
|
||||
EMOTIONAL_MEMORY: '情绪记忆',
|
||||
EPISODIC_MEMORY: '情景记忆',
|
||||
FORGETTING_MANAGEMENT: '遗忘',
|
||||
|
||||
endUserProfile: '核心档案',
|
||||
editEndUserProfile: '编辑',
|
||||
@@ -1933,6 +1936,7 @@ export const zh = {
|
||||
status_code: '状态码',
|
||||
max_attempts: '最大重试次数',
|
||||
retry_interval: '重试间隔',
|
||||
errorBranch: '异常分支',
|
||||
},
|
||||
'jinja-render': {
|
||||
template: '代码',
|
||||
@@ -2246,5 +2250,12 @@ export const zh = {
|
||||
orderPayInfo: '支付信息',
|
||||
create_time: '创建时间',
|
||||
},
|
||||
forgetDetail: {
|
||||
title: '遗忘管理系统帮助AI智能管理记忆生命周期,通过自动识别低价值记忆、设置遗忘策略和执行定期清理,优化记忆库存储空间,提升检索效率。',
|
||||
overviewTitle: '核心指标概览',
|
||||
totalMemory: '记忆总量',
|
||||
MemoryHealth: '记忆健康度',
|
||||
riskOfForgetting: '遗忘风险',
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import type {
|
||||
MemoryConfig,
|
||||
AiPromptModalRef,
|
||||
Source,
|
||||
ToolModalRef,
|
||||
ToolOption
|
||||
} from './types'
|
||||
import type { Model } from '@/views/ModelManagement/types'
|
||||
@@ -33,7 +32,6 @@ import { memoryConfigListUrl } from '@/api/memory'
|
||||
import CustomSelect from '@/components/CustomSelect'
|
||||
import aiPrompt from '@/assets/images/application/aiPrompt.png'
|
||||
import AiPromptModal from './components/AiPromptModal'
|
||||
import ToolModal from './components/ToolModal'
|
||||
import ToolList from './components/ToolList'
|
||||
|
||||
const DescWrapper: FC<{desc: string, className?: string}> = ({desc, className}) => {
|
||||
@@ -115,6 +113,7 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
|
||||
const [variableList, setVariableList] = useState<Variable[]>([])
|
||||
const [isSave, setIsSave] = useState(false)
|
||||
const initialized = useRef(false)
|
||||
const [toolList, setToolList] = useState<ToolOption[]>([])
|
||||
|
||||
// 初始化完成标记
|
||||
useEffect(() => {
|
||||
@@ -143,6 +142,11 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
|
||||
if (isSave) return
|
||||
setIsSave(true)
|
||||
}, [values])
|
||||
useEffect(() => {
|
||||
if (!initialized.current) return
|
||||
if (isSave) return
|
||||
setIsSave(true)
|
||||
}, [toolList])
|
||||
|
||||
useEffect(() => {
|
||||
getModels()
|
||||
@@ -294,7 +298,11 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
|
||||
...(item.config || {})
|
||||
}))
|
||||
} as KnowledgeConfig : null,
|
||||
tools: toolList
|
||||
tools: toolList.map(vo => ({
|
||||
tool_id: vo.tool_id,
|
||||
operation: vo.operation,
|
||||
enabled: vo.enabled
|
||||
}))
|
||||
}
|
||||
|
||||
console.log('params', rest, params)
|
||||
@@ -347,18 +355,6 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
|
||||
form.setFieldValue('system_prompt', value)
|
||||
}
|
||||
|
||||
const toolModalRef = useRef<ToolModalRef>(null)
|
||||
const [toolList, setToolList] = useState<ToolOption[]>([])
|
||||
const handleAddTool = () => {
|
||||
toolModalRef.current?.handleOpen()
|
||||
}
|
||||
const updateTools = (tool: ToolOption) => {
|
||||
const tools = [...toolList, tool]
|
||||
setToolList(tools)
|
||||
form.setFieldValue('tools', tools)
|
||||
}
|
||||
|
||||
console.log('toolList', toolList)
|
||||
return (
|
||||
<>
|
||||
{loading && <Spin fullscreen></Spin>}
|
||||
@@ -469,10 +465,6 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
|
||||
defaultModel={defaultModel}
|
||||
refresh={updatePrompt}
|
||||
/>
|
||||
<ToolModal
|
||||
ref={toolModalRef}
|
||||
refresh={updateTools}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -90,11 +90,19 @@ const AiPromptModal = forwardRef<AiPromptModalRef, AiPromptModalProps>(({
|
||||
switch (item.event) {
|
||||
case 'start':
|
||||
currentPromptValueRef.current = ''
|
||||
if (editorRef.current?.clear) {
|
||||
editorRef.current.clear();
|
||||
}
|
||||
break;
|
||||
case 'message':
|
||||
if (content) {
|
||||
currentPromptValueRef.current += content;
|
||||
form.setFieldsValue({ current_prompt: currentPromptValueRef.current })
|
||||
if (editorRef.current?.appendText) {
|
||||
editorRef.current.appendText(content);
|
||||
editorRef.current.scrollToBottom();
|
||||
} else {
|
||||
form.setFieldsValue({ current_prompt: currentPromptValueRef.current })
|
||||
}
|
||||
}
|
||||
if (desc) {
|
||||
setChatList(prev => {
|
||||
@@ -107,6 +115,8 @@ const AiPromptModal = forwardRef<AiPromptModalRef, AiPromptModalProps>(({
|
||||
break;
|
||||
case 'end':
|
||||
setLoading(false)
|
||||
// 流结束时同步表单值
|
||||
form.setFieldsValue({ current_prompt: currentPromptValueRef.current })
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@ import { LexicalComposer } from '@lexical/react/LexicalComposer';
|
||||
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
|
||||
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
|
||||
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
|
||||
import { $getSelection } from 'lexical';
|
||||
import { $getSelection, $getRoot, $createParagraphNode, $createTextNode, $isParagraphNode, $isTextNode } from 'lexical';
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
||||
import InitialValuePlugin from './plugin/InitialValuePlugin'
|
||||
import LineBreakPlugin from './plugin/LineBreakPlugin';
|
||||
@@ -12,6 +12,9 @@ import InsertTextPlugin from './plugin/InsertTextPlugin';
|
||||
|
||||
export interface EditorRef {
|
||||
insertText: (text: string) => void;
|
||||
appendText: (text: string) => void;
|
||||
clear: () => void;
|
||||
scrollToBottom: () => void;
|
||||
}
|
||||
|
||||
interface LexicalEditorProps {
|
||||
@@ -46,6 +49,41 @@ const EditorContent = forwardRef<EditorRef, LexicalEditorProps>(({
|
||||
selection.insertText(text);
|
||||
}
|
||||
});
|
||||
},
|
||||
appendText: (text: string) => {
|
||||
editor.update(() => {
|
||||
const root = $getRoot();
|
||||
const lastChild = root.getLastChild();
|
||||
if (lastChild && $isParagraphNode(lastChild)) {
|
||||
const lastTextNode = lastChild.getLastChild();
|
||||
if (lastTextNode && $isTextNode(lastTextNode)) {
|
||||
const currentText = lastTextNode.getTextContent();
|
||||
lastTextNode.setTextContent(currentText + text);
|
||||
} else {
|
||||
const textNode = $createTextNode(text);
|
||||
lastChild.append(textNode);
|
||||
}
|
||||
} else {
|
||||
const paragraph = $createParagraphNode();
|
||||
const textNode = $createTextNode(text);
|
||||
paragraph.append(textNode);
|
||||
root.append(paragraph);
|
||||
}
|
||||
});
|
||||
},
|
||||
clear: () => {
|
||||
editor.update(() => {
|
||||
const root = $getRoot();
|
||||
root.clear();
|
||||
const paragraph = $createParagraphNode();
|
||||
root.append(paragraph);
|
||||
});
|
||||
},
|
||||
scrollToBottom: () => {
|
||||
const editorElement = editor.getRootElement();
|
||||
if (editorElement) {
|
||||
editorElement.scrollTop = editorElement.scrollHeight;
|
||||
}
|
||||
}
|
||||
}), [editor]);
|
||||
|
||||
|
||||
@@ -1,21 +1,37 @@
|
||||
import { type FC, useEffect } from 'react';
|
||||
import { type FC, useEffect, useRef } from 'react';
|
||||
import { $getRoot, $createParagraphNode, $createTextNode } from 'lexical';
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
||||
|
||||
// 设置初始值的插件
|
||||
const InitialValuePlugin: FC<{ value?: string }> = ({ value }) => {
|
||||
const [editor] = useLexicalComposerContext();
|
||||
const lastValueRef = useRef<string | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (value) {
|
||||
// 只有当value真正发生变化时才更新
|
||||
if (lastValueRef.current !== value) {
|
||||
editor.update(() => {
|
||||
const root = $getRoot();
|
||||
const currentText = root.getTextContent();
|
||||
|
||||
// 如果当前内容和新值相同,则不更新
|
||||
if (currentText === (value || '')) {
|
||||
return;
|
||||
}
|
||||
|
||||
root.clear();
|
||||
const paragraph = $createParagraphNode();
|
||||
const textNode = $createTextNode(value);
|
||||
paragraph.append(textNode);
|
||||
root.append(paragraph);
|
||||
if (value) {
|
||||
const paragraph = $createParagraphNode();
|
||||
const textNode = $createTextNode(value);
|
||||
paragraph.append(textNode);
|
||||
root.append(paragraph);
|
||||
} else {
|
||||
// 当value为undefined或空时,创建一个空段落
|
||||
const paragraph = $createParagraphNode();
|
||||
root.append(paragraph);
|
||||
}
|
||||
});
|
||||
lastValueRef.current = value;
|
||||
}
|
||||
}, [editor, value]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user