fix: plugin run & setting quote variables (#2150)

* fix

* fix

* change variables & variablelabels show condition

* fix type

* fix
This commit is contained in:
heheer
2024-07-25 18:01:43 +08:00
committed by GitHub
parent 55cefccad1
commit 5906daff9f
12 changed files with 89 additions and 51 deletions

View File

@@ -229,6 +229,24 @@ export const updatePluginInputByVariables = (
); );
}; };
export const filterPluginInputVariables = (
variables: Record<string, any>,
nodes: RuntimeNodeItemType[]
) => {
const pluginInputNode = nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput);
if (!pluginInputNode) return variables;
return Object.keys(variables).reduce(
(acc, key) => {
if (!pluginInputNode.inputs.find((input) => input.key === key)) {
acc[key] = variables[key];
}
return acc;
},
{} as Record<string, any>
);
};
export function replaceVariableLabel({ export function replaceVariableLabel({
text, text,
nodes, nodes,

View File

@@ -1,9 +1,4 @@
import { import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
DispatchNodeResponseKeyEnum,
SseResponseEventEnum
} from '@fastgpt/global/core/workflow/runtime/constants';
import { responseWrite } from '../../../../common/response';
import { textAdaptGptResponse } from '@fastgpt/global/core/workflow/runtime/utils';
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type'; import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants'; import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type'; import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';

View File

@@ -80,7 +80,6 @@ const JSONEditor = ({
const lineContent = model.getLineContent(position.lineNumber); const lineContent = model.getLineContent(position.lineNumber);
if (context.triggerCharacter) { if (context.triggerCharacter) {
console.log(context.triggerCharacter);
triggerChar.current = context.triggerCharacter; triggerChar.current = context.triggerCharacter;
} }
const word = model.getWordUntilPosition(position); const word = model.getWordUntilPosition(position);

View File

@@ -13,7 +13,7 @@ import { VariableNode } from './plugins/VariablePlugin/node';
import { EditorState, LexicalEditor } from 'lexical'; import { EditorState, LexicalEditor } from 'lexical';
import OnBlurPlugin from './plugins/OnBlurPlugin'; import OnBlurPlugin from './plugins/OnBlurPlugin';
import MyIcon from '../../Icon'; import MyIcon from '../../Icon';
import { EditorVariablePickerType } from './type.d'; import { EditorVariableLabelPickerType, EditorVariablePickerType } from './type.d';
import { getNanoid } from '@fastgpt/global/common/string/tools'; import { getNanoid } from '@fastgpt/global/common/string/tools';
import FocusPlugin from './plugins/FocusPlugin'; import FocusPlugin from './plugins/FocusPlugin';
import { textToEditorState } from './utils'; import { textToEditorState } from './utils';
@@ -21,6 +21,7 @@ import { MaxLengthPlugin } from './plugins/MaxLengthPlugin';
import { VariableLabelNode } from './plugins/VariableLabelPlugin/node'; import { VariableLabelNode } from './plugins/VariableLabelPlugin/node';
import VariableLabelPlugin from './plugins/VariableLabelPlugin'; import VariableLabelPlugin from './plugins/VariableLabelPlugin';
import { useDeepCompareEffect } from 'ahooks'; import { useDeepCompareEffect } from 'ahooks';
import VariablePickerPlugin from './plugins/VariablePickerPlugin';
export default function Editor({ export default function Editor({
h = 200, h = 200,
@@ -29,6 +30,7 @@ export default function Editor({
showOpenModal = true, showOpenModal = true,
onOpenModal, onOpenModal,
variables, variables,
variableLabels,
onChange, onChange,
onBlur, onBlur,
value, value,
@@ -41,6 +43,7 @@ export default function Editor({
showOpenModal?: boolean; showOpenModal?: boolean;
onOpenModal?: () => void; onOpenModal?: () => void;
variables: EditorVariablePickerType[]; variables: EditorVariablePickerType[];
variableLabels: EditorVariableLabelPickerType[];
onChange?: (editorState: EditorState, editor: LexicalEditor) => void; onChange?: (editorState: EditorState, editor: LexicalEditor) => void;
onBlur?: (editor: LexicalEditor) => void; onBlur?: (editor: LexicalEditor) => void;
value?: string; value?: string;
@@ -130,9 +133,10 @@ export default function Editor({
}); });
}} }}
/> />
<VariableLabelPickerPlugin variables={variables} isFocus={focus} /> <VariableLabelPlugin variables={variableLabels} />
<VariableLabelPickerPlugin variables={variableLabels} isFocus={focus} />
<VariablePlugin variables={variables} /> <VariablePlugin variables={variables} />
<VariableLabelPlugin variables={variables} /> <VariablePickerPlugin variables={variableLabels.length > 0 ? [] : variables} />
<OnBlurPlugin onBlur={onBlur} /> <OnBlurPlugin onBlur={onBlur} />
</LexicalComposer> </LexicalComposer>
{showResize && ( {showResize && (

View File

@@ -5,13 +5,14 @@ import Editor from './Editor';
import MyModal from '../../MyModal'; import MyModal from '../../MyModal';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { EditorState, type LexicalEditor } from 'lexical'; import { EditorState, type LexicalEditor } from 'lexical';
import { EditorVariablePickerType } from './type.d'; import { EditorVariableLabelPickerType, EditorVariablePickerType } from './type.d';
import { useCallback, useTransition } from 'react'; import { useCallback, useTransition } from 'react';
const PromptEditor = ({ const PromptEditor = ({
showOpenModal = true, showOpenModal = true,
showResize = true, showResize = true,
variables = [], variables = [],
variableLabels = [],
value, value,
onChange, onChange,
onBlur, onBlur,
@@ -24,6 +25,7 @@ const PromptEditor = ({
showOpenModal?: boolean; showOpenModal?: boolean;
showResize?: boolean; showResize?: boolean;
variables?: EditorVariablePickerType[]; variables?: EditorVariablePickerType[];
variableLabels?: EditorVariableLabelPickerType[];
value?: string; value?: string;
onChange?: (text: string) => void; onChange?: (text: string) => void;
onBlur?: (text: string) => void; onBlur?: (text: string) => void;
@@ -55,6 +57,7 @@ const PromptEditor = ({
showOpenModal={showOpenModal} showOpenModal={showOpenModal}
onOpenModal={onOpen} onOpenModal={onOpen}
variables={variables} variables={variables}
variableLabels={variableLabels}
h={h} h={h}
maxLength={maxLength} maxLength={maxLength}
value={value} value={value}
@@ -71,6 +74,7 @@ const PromptEditor = ({
showResize showResize
showOpenModal={false} showOpenModal={false}
variables={variables} variables={variables}
variableLabels={variableLabels}
value={value} value={value}
onChange={onChangeInput} onChange={onChangeInput}
onBlur={onBlurInput} onBlur={onBlurInput}

View File

@@ -6,31 +6,31 @@ import { useCallback, useState } from 'react';
import * as ReactDOM from 'react-dom'; import * as ReactDOM from 'react-dom';
import { Box, Flex } from '@chakra-ui/react'; import { Box, Flex } from '@chakra-ui/react';
import { useBasicTypeaheadTriggerMatch } from '../../utils'; import { useBasicTypeaheadTriggerMatch } from '../../utils';
import { EditorVariablePickerType } from '../../type'; import { EditorVariableLabelPickerType } from '../../type';
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants'; import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Avatar from '../../../../Avatar'; import Avatar from '../../../../Avatar';
type EditorVariablePickerType1 = { interface EditorVariableItemType {
key: string; key: string;
label: string; label: string;
required?: boolean; required?: boolean;
icon?: string; icon?: string;
valueType?: WorkflowIOValueTypeEnum; valueType?: WorkflowIOValueTypeEnum;
index: number; index: number;
}; }
interface TransformedParent { interface TransformedParent {
id: string; id: string;
label: string; label: string;
avatar: string; avatar: string;
children: EditorVariablePickerType1[]; children: EditorVariableItemType[];
} }
export default function VariableLabelPickerPlugin({ export default function VariableLabelPickerPlugin({
variables, variables,
isFocus isFocus
}: { }: {
variables: EditorVariablePickerType[]; variables: EditorVariableLabelPickerType[];
isFocus: boolean; isFocus: boolean;
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -110,7 +110,7 @@ export default function VariableLabelPickerPlugin({
</Box> </Box>
)} )}
{variableFilter(variables, queryString || '').length > 0 ? ( {variableFilter(variables, queryString || '').length > 0 ? (
transformData(variableFilter(variables, queryString || '')).map((item) => { transformVariables(variableFilter(variables, queryString || '')).map((item) => {
return ( return (
<Flex <Flex
key={item.id} key={item.id}
@@ -192,14 +192,14 @@ export default function VariableLabelPickerPlugin({
); );
} }
function transformData(data: EditorVariablePickerType[]): TransformedParent[] { function transformVariables(variables: EditorVariableLabelPickerType[]): TransformedParent[] {
const transformedData: TransformedParent[] = []; const transformedData: TransformedParent[] = [];
const parentMap: { [key: string]: TransformedParent } = {}; const parentMap: { [key: string]: TransformedParent } = {};
data.forEach((item, index) => { variables.forEach((item, index) => {
const parentId = item.parent!.id; const parentId = item.parent.id;
const parentLabel = item.parent!.label; const parentLabel = item.parent.label;
const parentAvatar = item.parent!.avatar; const parentAvatar = item.parent.avatar;
if (!parentMap[parentId]) { if (!parentMap[parentId]) {
parentMap[parentId] = { parentMap[parentId] = {
@@ -218,8 +218,8 @@ function transformData(data: EditorVariablePickerType[]): TransformedParent[] {
}); });
const addedParents = new Set<string>(); const addedParents = new Set<string>();
data.forEach((item) => { variables.forEach((item) => {
const parentId = item.parent!.id; const parentId = item.parent.id;
if (!addedParents.has(parentId)) { if (!addedParents.has(parentId)) {
transformedData.push(parentMap[parentId]); transformedData.push(parentMap[parentId]);
addedParents.add(parentId); addedParents.add(parentId);
@@ -230,15 +230,15 @@ function transformData(data: EditorVariablePickerType[]): TransformedParent[] {
} }
function variableFilter( function variableFilter(
data: EditorVariablePickerType[], variables: EditorVariableLabelPickerType[],
queryString: string queryString: string
): EditorVariablePickerType[] { ): EditorVariableLabelPickerType[] {
const lowerCaseQuery = queryString.toLowerCase(); const lowerCaseQuery = queryString.toLowerCase();
return data.filter((item) => { return variables.filter((item) => {
const labelMatch = item.label.toLowerCase().includes(lowerCaseQuery); const labelMatch = item.label.toLowerCase().includes(lowerCaseQuery);
const keyMatch = item.key.toLowerCase().includes(lowerCaseQuery); const keyMatch = item.key.toLowerCase().includes(lowerCaseQuery);
const parentLabelMatch = item.parent!.label.toLowerCase().includes(lowerCaseQuery); const parentLabelMatch = item.parent.label.toLowerCase().includes(lowerCaseQuery);
return labelMatch || keyMatch || parentLabelMatch; return labelMatch || keyMatch || parentLabelMatch;
}); });

View File

@@ -1,6 +1,6 @@
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { EditorVariablePickerType } from '../../type'; import { EditorVariableLabelPickerType } from '../../type';
import { useCallback, useEffect, useMemo } from 'react'; import { useCallback, useEffect } from 'react';
import { $createVariableLabelNode, VariableLabelNode } from './node'; import { $createVariableLabelNode, VariableLabelNode } from './node';
import { TextNode } from 'lexical'; import { TextNode } from 'lexical';
import { getHashtagRegexString } from './utils'; import { getHashtagRegexString } from './utils';
@@ -12,7 +12,7 @@ const REGEX = new RegExp(getHashtagRegexString(), 'i');
export default function VariableLabelPlugin({ export default function VariableLabelPlugin({
variables variables
}: { }: {
variables: EditorVariablePickerType[]; variables: EditorVariableLabelPickerType[];
}) { }) {
const [editor] = useLexicalComposerContext(); const [editor] = useLexicalComposerContext();
useEffect(() => { useEffect(() => {

View File

@@ -6,7 +6,15 @@ export type EditorVariablePickerType = {
required?: boolean; required?: boolean;
icon?: string; icon?: string;
valueType?: WorkflowIOValueTypeEnum; valueType?: WorkflowIOValueTypeEnum;
parent?: { };
export type EditorVariableLabelPickerType = {
key: string;
label: string;
required?: boolean;
icon?: string;
valueType?: WorkflowIOValueTypeEnum;
parent: {
id: string; id: string;
label: string; label: string;
avatar?: string; avatar?: string;

View File

@@ -14,7 +14,10 @@ import { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type'
import { removeEmptyUserInput } from '@fastgpt/global/core/chat/utils'; import { removeEmptyUserInput } from '@fastgpt/global/core/chat/utils';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { updatePluginInputByVariables } from '@fastgpt/global/core/workflow/utils'; import {
filterPluginInputVariables,
updatePluginInputByVariables
} from '@fastgpt/global/core/workflow/utils';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt'; import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
import { ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type'; import { ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type';
@@ -63,6 +66,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
// Plugin need to replace inputs // Plugin need to replace inputs
if (isPlugin) { if (isPlugin) {
nodes = updatePluginInputByVariables(nodes, variables); nodes = updatePluginInputByVariables(nodes, variables);
variables = filterPluginInputVariables(variables, nodes);
} else { } else {
if (!userInput) { if (!userInput) {
throw new Error('Params Error'); throw new Error('Params Error');

View File

@@ -54,7 +54,10 @@ import { NextAPI } from '@/service/middleware/entry';
import { getAppLatestVersion } from '@fastgpt/service/core/app/controller'; import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { updatePluginInputByVariables } from '@fastgpt/global/core/workflow/utils'; import {
filterPluginInputVariables,
updatePluginInputByVariables
} from '@fastgpt/global/core/workflow/utils';
import { getNanoid } from '@fastgpt/global/common/string/tools'; import { getNanoid } from '@fastgpt/global/common/string/tools';
import { import {
getPluginInputsFromStoreNodes, getPluginInputsFromStoreNodes,
@@ -235,6 +238,11 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
) )
: storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes)); : storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes));
const runtimeVariables = filterPluginInputVariables(
variables,
storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes))
);
/* start flow controller */ /* start flow controller */
const { flowResponses, flowUsages, assistantResponses, newVariables } = await (async () => { const { flowResponses, flowUsages, assistantResponses, newVariables } = await (async () => {
if (app.version === 'v2') { if (app.version === 'v2') {
@@ -249,7 +257,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
responseChatItemId, responseChatItemId,
runtimeNodes, runtimeNodes,
runtimeEdges: initWorkflowEdgeStatus(edges), runtimeEdges: initWorkflowEdgeStatus(edges),
variables, variables: runtimeVariables,
query: removeEmptyUserInput(userQuestion.value), query: removeEmptyUserInput(userQuestion.value),
histories: newHistories, histories: newHistories,
stream, stream,

View File

@@ -104,7 +104,7 @@ const EditForm = ({
onClose: onCloseToolsSelect onClose: onCloseToolsSelect
} = useDisclosure(); } = useDisclosure();
const formatVariables: any = useMemo( const formatVariables = useMemo(
() => () =>
formatEditorVariablePickerIcon([ formatEditorVariablePickerIcon([
...getSystemVariables(t), ...getSystemVariables(t),
@@ -186,6 +186,7 @@ const EditForm = ({
})); }));
}); });
}} }}
variableLabels={formatVariables}
variables={formatVariables} variables={formatVariables}
placeholder={t('common:core.app.tip.chatNodeSystemPromptTip')} placeholder={t('common:core.app.tip.chatNodeSystemPromptTip')}
title={t('common:core.ai.Prompt')} title={t('common:core.ai.Prompt')}

View File

@@ -20,18 +20,16 @@ const TextareaRender = ({ inputs = [], item, nodeId }: RenderInputProps) => {
// get variable // get variable
const variables = useCreation(() => { const variables = useCreation(() => {
const currentNode = nodeList.find((node) => node.nodeId === nodeId); const currentNode = nodeList.find((node) => node.nodeId === nodeId)!;
const nodeVariables = formatEditorVariablePickerIcon( const nodeVariables = getNodeDynamicInputs(nodeId).map((item) => ({
getNodeDynamicInputs(nodeId).map((item) => ({
key: item.key, key: item.key,
label: item.label, label: item.label,
parent: { parent: {
id: currentNode?.nodeId, id: currentNode.nodeId,
label: currentNode?.name, label: currentNode.name,
avatar: currentNode?.avatar avatar: currentNode.avatar
} }
})) }));
);
const sourceNodes = computedNodeInputReference({ const sourceNodes = computedNodeInputReference({
nodeId, nodeId,
@@ -61,9 +59,7 @@ const TextareaRender = ({ inputs = [], item, nodeId }: RenderInputProps) => {
}) })
.flat(); .flat();
const formatSourceNodeVariables = formatEditorVariablePickerIcon(sourceNodeVariables); return [...nodeVariables, ...sourceNodeVariables];
return [...nodeVariables, ...formatSourceNodeVariables];
}, [nodeList, edges, inputs, t]); }, [nodeList, edges, inputs, t]);
const onChange = useCallback( const onChange = useCallback(
@@ -84,6 +80,7 @@ const TextareaRender = ({ inputs = [], item, nodeId }: RenderInputProps) => {
const Render = useMemo(() => { const Render = useMemo(() => {
return ( return (
<PromptEditor <PromptEditor
variableLabels={variables}
variables={variables} variables={variables}
title={t(item.label as any)} title={t(item.label as any)}
maxLength={item.maxLength} maxLength={item.maxLength}