Test version (#4792)

* plugin node version select (#4760)

* plugin node version select

* type

* fix

* fix

* perf: version list

* fix node version (#4787)

* change my select

* fix-ui

* fix test

* add test

* fix

* remove invalid version field

* filter deprecated field

* fix: claude tool call

* fix: test

---------

Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
Archer
2025-05-12 22:27:01 +08:00
committed by GitHub
parent 3cc6b8a17a
commit 0ef3d40296
69 changed files with 1024 additions and 599 deletions

View File

@@ -331,7 +331,7 @@ export const getQuotePrompt = (version?: string, role: 'user' | 'system' = 'user
};
// Document quote prompt
export const getDocumentQuotePrompt = (version: string) => {
export const getDocumentQuotePrompt = (version?: string) => {
const promptMap = {
['4.9.2']: `将 <FilesContent></FilesContent> 中的内容作为本次对话的参考:
<FilesContent>

View File

@@ -1,4 +1,5 @@
export const getPromptByVersion = (version?: string, promptMap: Record<string, string> = {}) => {
// 版本号大的在前面
const versions = Object.keys(promptMap).sort((a, b) => {
const [majorA, minorA, patchA] = a.split('.').map(Number);
const [majorB, minorB, patchB] = b.split('.').map(Number);
@@ -15,5 +16,5 @@ export const getPromptByVersion = (version?: string, promptMap: Record<string, s
if (version in promptMap) {
return promptMap[version];
}
return promptMap[versions[versions.length - 1]];
return promptMap[versions[0]];
};

View File

@@ -218,7 +218,6 @@ export const FlowValueTypeMap: Record<
};
export const EDGE_TYPE = 'default';
export const defaultNodeVersion = '481';
export const chatHistoryValueDesc = `{
obj: System | Human | AI;
@@ -236,3 +235,10 @@ export const datasetQuoteValueDesc = `{
export const datasetSelectValueDesc = `{
datasetId: string;
}[]`;
export const AppNodeFlowNodeTypeMap: Record<any, boolean> = {
[FlowNodeTypeEnum.pluginModule]: true,
[FlowNodeTypeEnum.appModule]: true,
[FlowNodeTypeEnum.tool]: true,
[FlowNodeTypeEnum.toolSet]: true
};

View File

@@ -101,7 +101,7 @@ export type RuntimeNodeItemType = {
outputs: FlowNodeOutputItemType[];
pluginId?: string; // workflow id / plugin id
version: string;
version?: string;
};
export type RuntimeEdgeItemType = StoreEdgeItemType & {

View File

@@ -25,7 +25,6 @@ export const RunAppModule: FlowNodeTemplateType = {
name: i18nT('workflow:application_call'),
intro: i18nT('workflow:select_another_application_to_call'),
showStatus: true,
version: '481',
isTool: true,
inputs: [
{

View File

@@ -19,7 +19,6 @@ import {
Input_Template_UserChatInput,
Input_Template_File_Link
} from '../../input';
import { chatNodeSystemPromptTip, systemPromptTip } from '../../tip';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
@@ -121,12 +120,7 @@ export const AiChatModule: FlowNodeTemplateType = {
valueType: WorkflowIOValueTypeEnum.string
},
// settings modal ---
{
...Input_Template_System_Prompt,
label: i18nT('common:core.ai.Prompt'),
description: systemPromptTip,
placeholder: chatNodeSystemPromptTip
},
Input_Template_System_Prompt,
Input_Template_History,
Input_Template_Dataset_Quote,
Input_Template_File_Link,

View File

@@ -18,7 +18,6 @@ export const AssignedAnswerModule: FlowNodeTemplateType = {
name: i18nT('workflow:assigned_reply'),
intro: i18nT('workflow:intro_assigned_reply'),
courseUrl: '/docs/guide/dashboard/workflow/reply/',
version: '481',
isTool: true,
inputs: [
{

View File

@@ -18,7 +18,6 @@ export const CustomFeedbackNode: FlowNodeTemplateType = {
name: i18nT('workflow:custom_feedback'),
intro: i18nT('workflow:intro_custom_feedback'),
courseUrl: '/docs/guide/dashboard/workflow/custom_feedback/',
version: '486',
inputs: [
{
key: NodeInputKeyEnum.textareaInput,

View File

@@ -42,7 +42,6 @@ export const DatasetConcatModule: FlowNodeTemplateType = {
intro: i18nT('workflow:intro_knowledge_base_search_merge'),
showStatus: false,
version: '486',
courseUrl: '/docs/guide/dashboard/workflow/knowledge_base_search_merge/',
inputs: [
{

View File

@@ -28,7 +28,6 @@ export const HttpNode468: FlowNodeTemplateType = {
showStatus: true,
isTool: true,
courseUrl: '/docs/guide/dashboard/workflow/http/',
version: '481',
inputs: [
{
...Input_Template_DynamicInput,

View File

@@ -24,7 +24,6 @@ export const IfElseNode: FlowNodeTemplateType = {
intro: i18nT('workflow:execute_different_branches_based_on_conditions'),
showStatus: true,
courseUrl: '/docs/guide/dashboard/workflow/tfswitch/',
version: '481',
inputs: [
{
key: NodeInputKeyEnum.ifElseList,

View File

@@ -23,7 +23,6 @@ export const FormInputNode: FlowNodeTemplateType = {
name: i18nT('app:workflow.form_input'),
intro: i18nT(`app:workflow.form_input_tip`),
isTool: true,
version: '4811',
inputs: [
{
key: NodeInputKeyEnum.description,

View File

@@ -24,7 +24,6 @@ export const UserSelectNode: FlowNodeTemplateType = {
name: i18nT('app:workflow.user_select'),
intro: i18nT(`app:workflow.user_select_tip`),
isTool: true,
version: '489',
courseUrl: '/docs/guide/dashboard/workflow/user-selection/',
inputs: [
{

View File

@@ -33,7 +33,6 @@ export const LafModule: FlowNodeTemplateType = {
showStatus: true,
isTool: true,
courseUrl: '/docs/guide/dashboard/workflow/laf/',
version: '481',
inputs: [
{
...Input_Template_DynamicInput,

View File

@@ -29,7 +29,6 @@ export const LoopNode: FlowNodeTemplateType = {
name: i18nT('workflow:loop'),
intro: i18nT('workflow:intro_loop'),
showStatus: true,
version: '4811',
courseUrl: '/docs/guide/dashboard/workflow/loop/',
inputs: [
{

View File

@@ -19,7 +19,6 @@ export const LoopEndNode: FlowNodeTemplateType = {
avatar: 'core/workflow/template/loopEnd',
name: i18nT('workflow:loop_end'),
showStatus: false,
version: '4811',
inputs: [
{
key: NodeInputKeyEnum.loopEndInput,

View File

@@ -24,7 +24,6 @@ export const LoopStartNode: FlowNodeTemplateType = {
unique: true,
forbidDelete: true,
showStatus: false,
version: '4811',
inputs: [
{
key: NodeInputKeyEnum.loopStartInput,

View File

@@ -15,7 +15,6 @@ export const PluginConfigNode: FlowNodeTemplateType = {
intro: '',
unique: true,
forbidDelete: true,
version: '4811',
inputs: [],
outputs: []
};

View File

@@ -16,7 +16,6 @@ export const PluginInputModule: FlowNodeTemplateType = {
name: i18nT('workflow:plugin_input'),
intro: i18nT('workflow:intro_plugin_input'),
showStatus: false,
version: '481',
inputs: [],
outputs: []
};

View File

@@ -16,7 +16,6 @@ export const PluginOutputModule: FlowNodeTemplateType = {
name: i18nT('workflow:template.plugin_output'),
intro: i18nT('workflow:intro_custom_plugin_output'),
showStatus: false,
version: '481',
inputs: [],
outputs: []
};

View File

@@ -13,7 +13,6 @@ export const RunAppNode: FlowNodeTemplateType = {
name: '',
showStatus: false,
isTool: false,
version: '481',
inputs: [], // [{key:'pluginId'},...]
outputs: []
};

View File

@@ -13,7 +13,6 @@ export const RunPluginModule: FlowNodeTemplateType = {
name: '',
showStatus: false,
isTool: true,
version: '481',
inputs: [], // [{key:'pluginId'},...]
outputs: []
};

View File

@@ -13,7 +13,6 @@ export const RunToolNode: FlowNodeTemplateType = {
name: '',
showStatus: false,
isTool: true,
version: '4.9.6',
inputs: [],
outputs: []
};

View File

@@ -13,7 +13,6 @@ export const RunToolSetNode: FlowNodeTemplateType = {
name: '',
showStatus: false,
isTool: true,
version: '4.9.6',
inputs: [],
outputs: []
};

View File

@@ -27,7 +27,6 @@ export const CodeNode: FlowNodeTemplateType = {
intro: i18nT('workflow:execute_a_simple_script_code_usually_for_complex_data_processing'),
showStatus: true,
courseUrl: '/docs/guide/dashboard/workflow/sandbox/',
version: '482',
inputs: [
{
...Input_Template_DynamicInput,

View File

@@ -13,7 +13,6 @@ export const StopToolNode: FlowNodeTemplateType = {
avatar: 'core/workflow/template/stopTool',
name: i18nT('workflow:tool_call_termination'),
intro: i18nT('workflow:intro_tool_call_termination'),
version: '481',
inputs: [],
outputs: []
};

View File

@@ -15,7 +15,6 @@ export const SystemConfigNode: FlowNodeTemplateType = {
intro: '',
unique: true,
forbidDelete: true,
version: '481',
inputs: [],
outputs: []
};

View File

@@ -24,7 +24,6 @@ export const TextEditorNode: FlowNodeTemplateType = {
name: i18nT('workflow:text_concatenation'),
intro: i18nT('workflow:intro_text_concatenation'),
courseUrl: '/docs/guide/dashboard/workflow/text_editor/',
version: '4813',
inputs: [
{
key: NodeInputKeyEnum.textareaInput,

View File

@@ -13,7 +13,6 @@ export const ToolParamsNode: FlowNodeTemplateType = {
avatar: 'core/workflow/template/toolParams',
name: i18nT('workflow:tool_custom_field'),
intro: i18nT('workflow:intro_tool_params_config'),
version: '4811',
isTool: true,
inputs: [],
outputs: []

View File

@@ -19,7 +19,6 @@ export const VariableUpdateNode: FlowNodeTemplateType = {
intro: i18nT('workflow:update_specified_node_output_or_global_variable'),
showStatus: false,
isTool: true,
version: '481',
courseUrl: '/docs/guide/dashboard/workflow/variable_update/',
inputs: [
{

View File

@@ -30,7 +30,6 @@ export const WorkflowStart: FlowNodeTemplateType = {
intro: '',
forbidDelete: true,
unique: true,
version: '481',
inputs: [{ ...Input_Template_UserChatInput, toolDescription: i18nT('workflow:user_question') }],
outputs: [
{

View File

@@ -37,7 +37,10 @@ export type WorkflowTemplateType = {
intro?: string;
author?: string;
courseUrl?: string;
version: string;
version?: string;
versionLabel?: string;
isLatestVersion?: boolean;
showStatus?: boolean;
weight?: number;

View File

@@ -63,6 +63,8 @@ export type FlowNodeInputItemType = InputComponentPropsType & {
canSelectFile?: boolean;
canSelectImg?: boolean;
maxFiles?: number;
deprecated?: boolean;
};
export type FlowNodeOutputItemType = {
@@ -86,6 +88,8 @@ export type FlowNodeOutputItemType = {
// component params
customFieldConfig?: CustomFieldConfigType;
deprecated?: boolean;
};
export type ReferenceItemValueType = [string, string | undefined];

View File

@@ -34,7 +34,10 @@ export type FlowNodeCommonType = {
name: string;
intro?: string; // template list intro
showStatus?: boolean; // chatting response step status
version: string;
version?: string;
versionLabel?: string; // Just ui show
isLatestVersion?: boolean; // Just ui show
// data
inputs: FlowNodeInputItemType[];
@@ -48,7 +51,7 @@ export type FlowNodeCommonType = {
};
export type PluginDataType = {
version: string;
version?: string;
diagram?: string;
userGuide?: string;
courseUrl?: string;

View File

@@ -1,5 +1,5 @@
import { type FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node.d';
import { FlowNodeTypeEnum, defaultNodeVersion } from '@fastgpt/global/core/workflow/node/constant';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import {
appData2FlowNodeIO,
pluginData2FlowNodeIO,
@@ -14,10 +14,16 @@ import { cloneDeep } from 'lodash';
import { MongoApp } from '../schema';
import { type SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type';
import { getSystemPluginTemplates } from '../../../../plugins/register';
import { getAppLatestVersion, getAppVersionById } from '../version/controller';
import {
checkIsLatestVersion,
getAppLatestVersion,
getAppVersionById
} from '../version/controller';
import { type PluginRuntimeType } from '@fastgpt/global/core/plugin/type';
import { MongoSystemPlugin } from './systemPluginSchema';
import { PluginErrEnum } from '@fastgpt/global/common/error/code/plugin';
import { MongoAppVersion } from '../version/schema';
import { i18nT } from '../../../../web/i18n/utils';
/*
plugin id rule:
@@ -90,20 +96,34 @@ const getSystemPluginTemplateById = async (
/* Format plugin to workflow preview node data */
export async function getChildAppPreviewNode({
id
appId,
versionId
}: {
id: string;
appId: string;
versionId?: string;
}): Promise<FlowNodeTemplateType> {
const app: ChildAppType = await (async () => {
const { source, pluginId } = await splitCombinePluginId(id);
const { source, pluginId } = await splitCombinePluginId(appId);
if (source === PluginSourceEnum.personal) {
const item = await MongoApp.findById(id).lean();
const item = await MongoApp.findById(appId).lean();
if (!item) return Promise.reject('plugin not found');
const version = await getAppLatestVersion(id, item);
const version = await getAppVersionById({ appId, versionId, app: item });
if (!version.versionId) return Promise.reject('App version not found');
if (!version.versionId) return Promise.reject(i18nT('common:app_not_version'));
const versionData = await MongoAppVersion.findById(
version.versionId,
'_id versionName appId time'
).lean();
const isLatest = versionData
? await checkIsLatestVersion({
appId,
versionId: versionData._id
})
: true;
return {
id: String(item._id),
@@ -118,7 +138,11 @@ export async function getChildAppPreviewNode({
chatConfig: version.chatConfig
},
templateType: FlowNodeTemplateTypeEnum.teamApp,
version: version.versionId,
versionLabel: versionData?.versionName || '',
isLatestVersion: isLatest,
originCost: 0,
currentCost: 0,
hasTokenFee: false,
@@ -175,7 +199,11 @@ export async function getChildAppPreviewNode({
userGuide: app.userGuide,
showStatus: app.showStatus,
isTool: true,
version: app.version,
versionLabel: app.versionLabel,
isLatestVersion: app.isLatestVersion,
sourceHandle: isToolSet
? getHandleConfig(false, false, false, false)
: getHandleConfig(true, true, true, true),
@@ -224,7 +252,7 @@ export async function getChildAppRuntimeById(
templateType: FlowNodeTemplateTypeEnum.teamApp,
// 用不到
version: item?.pluginData?.nodeVersion || defaultNodeVersion,
version: item?.pluginData?.nodeVersion,
originCost: 0,
currentCost: 0,
hasTokenFee: false,

View File

@@ -1,8 +1,14 @@
import { MongoDataset } from '../dataset/schema';
import { getEmbeddingModel } from '../ai/model';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import {
AppNodeFlowNodeTypeMap,
FlowNodeTypeEnum
} from '@fastgpt/global/core/workflow/node/constant';
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import type { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node';
import { MongoAppVersion } from './version/schema';
import { checkIsLatestVersion } from './version/controller';
import { Types } from '../../common/mongo';
export async function listAppDatasetDataByTeamIdAndDatasetIds({
teamId,
@@ -35,6 +41,45 @@ export async function rewriteAppWorkflowToDetail({
}) {
const datasetIdSet = new Set<string>();
// Add node(App Type) versionlabel and latest sign
const appNodes = nodes.filter((node) => AppNodeFlowNodeTypeMap[node.flowNodeType]);
const versionIds = appNodes
.filter((node) => node.version && Types.ObjectId.isValid(node.version))
.map((node) => node.version);
if (versionIds.length > 0) {
const versionDataList = await MongoAppVersion.find(
{
_id: { $in: versionIds }
},
'_id versionName appId time'
).lean();
const versionMap: Record<string, any> = {};
const isLatestChecks = await Promise.all(
versionDataList.map(async (version) => {
const isLatest = await checkIsLatestVersion({
appId: version.appId,
versionId: version._id
});
return { versionId: String(version._id), isLatest };
})
);
const isLatestMap = new Map(isLatestChecks.map((item) => [item.versionId, item.isLatest]));
versionDataList.forEach((version) => {
versionMap[String(version._id)] = version;
});
appNodes.forEach((node) => {
if (!node.version) return;
const versionData = versionMap[String(node.version)];
if (versionData) {
node.versionLabel = versionData.versionName;
node.isLatestVersion = isLatestMap.get(String(node.version)) || false;
}
});
}
// Get all dataset ids from nodes
nodes.forEach((node) => {
if (node.flowNodeType !== FlowNodeTypeEnum.datasetSearchNode) return;

View File

@@ -57,3 +57,22 @@ export const getAppVersionById = async ({
// If the version does not exist, the latest version is returned
return getAppLatestVersion(appId, app);
};
export const checkIsLatestVersion = async ({
appId,
versionId
}: {
appId: string;
versionId: string;
}) => {
const version = await MongoAppVersion.findOne(
{
appId,
isPublish: true,
_id: { $gt: versionId }
},
'_id'
).lean();
return !version;
};

View File

@@ -723,8 +723,8 @@ async function streamResponse({
}
// Parse tool calls
if (responseChoice?.tool_calls?.length) {
responseChoice.tool_calls.forEach((toolCall) => {
const index = toolCall.index;
responseChoice.tool_calls.forEach((toolCall, i) => {
const index = toolCall.index ?? i;
// Call new tool
if (toolCall.id || callingTool) {

View File

@@ -464,7 +464,7 @@ async function getChatMessages({
aiChatQuoteRole: AiChatQuoteRoleType; // user: replace user prompt; system: replace system prompt
datasetQuotePrompt?: string;
datasetQuoteText: string;
version: string;
version?: string;
useDatasetQuote: boolean;
histories: ChatItemType[];

View File

@@ -11,6 +11,7 @@ import type {
SystemVariablesType
} from '@fastgpt/global/core/workflow/runtime/type';
import type { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type.d';
import type { FlowNodeOutputItemType } from '@fastgpt/global/core/workflow/type/io.d';
import type {
AIChatItemValueItemType,
ChatHistoryItemResType,
@@ -549,7 +550,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
// Skip some special key
if (
[NodeInputKeyEnum.childrenNodeIdList, NodeInputKeyEnum.httpJsonBody].includes(
input.key as any
input.key as NodeInputKeyEnum
)
) {
params[input.key] = input.value;

View File

@@ -15,7 +15,6 @@ import {
useDisclosure,
MenuButton,
Box,
css,
Flex,
Input
} from '@chakra-ui/react';
@@ -32,13 +31,16 @@ import Avatar from '../Avatar';
* list: 列表数据
* isLoading: 是否加载中
* ScrollData: 分页滚动数据控制器 [useScrollPagination] 的返回值
* customOnOpen: 自定义打开回调
* customOnClose: 自定义关闭回调
* */
export type SelectProps<T = any> = Omit<ButtonProps, 'onChange'> & {
value?: T;
valueLabel?: string | React.ReactNode;
placeholder?: string;
isSearch?: boolean;
list: {
alias?: string;
alias?: string | React.ReactNode;
icon?: string;
iconSize?: string;
label: string | React.ReactNode;
@@ -49,18 +51,36 @@ export type SelectProps<T = any> = Omit<ButtonProps, 'onChange'> & {
isLoading?: boolean;
onChange?: (val: T) => any | Promise<any>;
ScrollData?: ReturnType<typeof useScrollPagination>['ScrollData'];
customOnOpen?: () => void;
customOnClose?: () => void;
};
export const menuItemStyles: MenuItemProps = {
borderRadius: 'sm',
py: 2,
display: 'flex',
alignItems: 'center',
_hover: {
backgroundColor: 'myGray.100'
},
_notLast: {
mb: 1
}
};
const MySelect = <T = any,>(
{
placeholder,
value,
valueLabel,
isSearch = false,
width = '100%',
list = [],
onChange,
isLoading = false,
ScrollData,
customOnOpen,
customOnClose,
...props
}: SelectProps<T>,
ref: ForwardedRef<{
@@ -72,21 +92,19 @@ const MySelect = <T = any,>(
const SelectedItemRef = useRef<HTMLDivElement>(null);
const SearchInputRef = useRef<HTMLInputElement>(null);
const menuItemStyles: MenuItemProps = {
borderRadius: 'sm',
py: 2,
display: 'flex',
alignItems: 'center',
_hover: {
backgroundColor: 'myGray.100'
},
_notLast: {
mb: 1
}
};
const { isOpen, onOpen, onClose } = useDisclosure();
const { isOpen, onOpen: defaultOnOpen, onClose: defaultOnClose } = useDisclosure();
const selectItem = useMemo(() => list.find((item) => item.value === value), [list, value]);
const onOpen = () => {
defaultOnOpen();
customOnOpen?.();
};
const onClose = () => {
defaultOnClose();
customOnClose?.();
};
const [search, setSearch] = useState('');
const filterList = useMemo(() => {
if (!isSearch || !search) {
@@ -105,6 +123,7 @@ const MySelect = <T = any,>(
}
}));
// Auto scroll
useEffect(() => {
if (isOpen && MenuListRef.current && SelectedItemRef.current) {
const menu = MenuListRef.current;
@@ -117,7 +136,7 @@ const MySelect = <T = any,>(
}
}, [isSearch, isOpen]);
const { runAsync: onclickChange, loading } = useRequest2((val: T) => onChange?.(val));
const { runAsync: onClickChange, loading } = useRequest2((val: T) => onChange?.(val));
const ListRender = useMemo(() => {
return (
@@ -138,7 +157,7 @@ const MySelect = <T = any,>(
})}
onClick={() => {
if (value !== item.value) {
onclickChange(item.value);
onClickChange(item.value);
}
}}
whiteSpace={'pre-wrap'}
@@ -161,7 +180,7 @@ const MySelect = <T = any,>(
))}
</>
);
}, [filterList, value]);
}, [filterList, onClickChange, value]);
const isSelecting = loading || isLoading;
@@ -200,36 +219,48 @@ const MySelect = <T = any,>(
: {})}
{...props}
>
<Flex alignItems={'center'}>
{isSelecting && <MyIcon mr={2} name={'common/loading'} w={'1rem'} />}
{isSearch && isOpen ? (
<Input
ref={SearchInputRef}
autoFocus
variant={'unstyled'}
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder={
selectItem?.alias ||
(typeof selectItem?.label === 'string' ? selectItem?.label : placeholder)
}
size={'sm'}
w={'100%'}
color={'myGray.700'}
onBlur={() => {
setTimeout(() => {
SearchInputRef?.current?.focus();
}, 0);
}}
/>
) : (
<>
{selectItem?.icon && (
<Avatar mr={2} src={selectItem.icon as any} w={selectItem.iconSize ?? '1rem'} />
)}
{selectItem?.alias || selectItem?.label || placeholder}
</>
)}
<Flex alignItems={'center'} justifyContent="space-between" w="100%">
<Flex alignItems={'center'}>
{isSelecting && <MyIcon mr={2} name={'common/loading'} w={'1rem'} />}
{valueLabel ? (
<>{valueLabel}</>
) : (
<>
{isSearch && isOpen ? (
<Input
ref={SearchInputRef}
autoFocus
variant={'unstyled'}
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder={
(typeof selectItem?.alias === 'string' ? selectItem?.alias : '') ||
(typeof selectItem?.label === 'string' ? selectItem?.label : placeholder)
}
size={'sm'}
w={'100%'}
color={'myGray.700'}
onBlur={() => {
setTimeout(() => {
SearchInputRef?.current?.focus();
}, 0);
}}
/>
) : (
<>
{selectItem?.icon && (
<Avatar
mr={2}
src={selectItem.icon as any}
w={selectItem.iconSize ?? '1rem'}
/>
)}
{selectItem?.alias || selectItem?.label || placeholder}
</>
)}
</>
)}
</Flex>
</Flex>
</MenuButton>
@@ -252,7 +283,7 @@ const MySelect = <T = any,>(
'0px 2px 4px rgba(161, 167, 179, 0.25), 0px 0px 1px rgba(121, 141, 159, 0.25);'
}
zIndex={99}
maxH={'40vh'}
maxH={'45vh'}
overflowY={'auto'}
>
{ScrollData ? <ScrollData>{ListRender}</ScrollData> : ListRender}

View File

@@ -190,6 +190,7 @@ export function useScrollPagination<
params = {},
EmptyTip,
showErrorToast = true,
disalbed = false,
...props
}: {
scrollLoadType?: 'top' | 'bottom';
@@ -198,6 +199,7 @@ export function useScrollPagination<
params?: Record<string, any>;
EmptyTip?: React.JSX.Element;
showErrorToast?: boolean;
disalbed?: boolean;
} & Parameters<typeof useRequest2>[1]
) {
const { t } = useTranslation();
@@ -345,10 +347,10 @@ export function useScrollPagination<
// Reload data
useRequest2(
async () => {
if (disalbed) return;
loadData(true);
},
{
manual: false,
...props
}
);

View File

@@ -1,4 +1,6 @@
{
"Click_to_delete_this_field": "Click to delete this field",
"Filed_is_deprecated": "This field is deprecated",
"MCP_tools_list_is_empty": "MCP tool not resolved",
"MCP_tools_parse_failed": "Failed to parse MCP address",
"MCP_tools_url": "MCP Address",
@@ -6,7 +8,6 @@
"MCP_tools_url_placeholder": "After filling in the MCP address, click Analysis",
"Role_setting": "Permission",
"Run": "Execute",
"team_tags_set": "Team tags",
"Team_Tags": "Team tags",
"ai_point_price": "Billing",
"ai_settings": "AI Configuration",
@@ -106,6 +107,7 @@
"no_mcp_tools_list": "No data yet, the MCP address needs to be parsed first",
"node_not_intro": "This node is not introduced",
"not_json_file": "Please select a JSON file",
"not_the_newest": "Not the latest",
"oaste_curl_string": "Enter CURL code",
"open_auto_execute": "Enable automatic execution",
"open_vision_function_tip": "Models with icon switches have image recognition capabilities. \nAfter being turned on, the model will parse the pictures in the file link and automatically parse the pictures in the user's question (user question ≤ 500 words).",
@@ -138,6 +140,7 @@
"stop_sign_placeholder": "Multiple serial numbers are separated by |, for example: aaa|stop",
"stream_response": "Stream",
"stream_response_tip": "Turning this switch off forces the model to use non-streaming mode and will not output content directly. \nIn the output of the AI reply, the content output by this model can be obtained for secondary processing.",
"team_tags_set": "Team tags",
"temperature": "Temperature",
"temperature_tip": "Range 0~10. \nThe larger the value, the more divergent the models answer is; the smaller the value, the more rigorous the answer.",
"template.hard_strict": "Strict Q&A template",

View File

@@ -96,6 +96,7 @@
"add_new_param": "Add new param",
"all_quotes": "All quotes",
"all_result": "Full Results",
"app_not_version": "This application has not been published, please publish it first",
"back": "Back",
"base_config": "Basic Configuration",
"bill_already_processed": "Order has been processed",

View File

@@ -1,4 +1,6 @@
{
"Click_to_delete_this_field": "点击删除该字段",
"Filed_is_deprecated": "该字段已弃用",
"MCP_tools_debug": "调试",
"MCP_tools_detail": "查看详情",
"MCP_tools_list": "工具列表",
@@ -10,7 +12,6 @@
"MCP_tools_url_placeholder": "填入 MCP 地址后,点击解析",
"Role_setting": "权限设置",
"Run": "运行",
"team_tags_set": "团队标签",
"Team_Tags": "团队标签",
"ai_point_price": "AI积分计费",
"ai_settings": "AI 配置",
@@ -110,6 +111,7 @@
"no_mcp_tools_list": "暂无数据,需先解析 MCP 地址",
"node_not_intro": "这个节点没有介绍",
"not_json_file": "请选择JSON文件",
"not_the_newest": "非最新版",
"oaste_curl_string": "输入 CURL 代码",
"open_auto_execute": "启用自动执行",
"open_vision_function_tip": "有图示开关的模型即拥有图片识别能力。若开启模型会解析文件链接里的图片并自动解析用户问题中的图片用户问题≤500字时生效。",
@@ -143,6 +145,7 @@
"stop_sign_placeholder": "多个序列号通过 | 隔开例如aaa|stop",
"stream_response": "流输出",
"stream_response_tip": "关闭该开关,可以强制模型使用非流模式,并且不会直接进行内容输出。可以在 AI 回复的输出中,获取本次模型输出的内容进行二次处理。",
"team_tags_set": "团队标签",
"temperature": "温度",
"temperature_tip": "范围 010。值越大代表模型回答越发散值越小代表回答越严谨。",
"template.hard_strict": "严格问答模板",

View File

@@ -96,6 +96,7 @@
"add_new_param": "新增参数",
"all_quotes": "全部引用",
"all_result": "完整结果",
"app_not_version": " 该应用未发布过,请先发布应用",
"back": "返回",
"base_config": "基础配置",
"bill_already_processed": "订单已处理",

View File

@@ -1,4 +1,6 @@
{
"Click_to_delete_this_field": "點擊刪除該字段",
"Filed_is_deprecated": "該字段已棄用",
"MCP_tools_list_is_empty": "未解析到 MCP 工具",
"MCP_tools_parse_failed": "解析 MCP 地址失敗",
"MCP_tools_url": "MCP 地址",
@@ -6,7 +8,6 @@
"MCP_tools_url_placeholder": "填入 MCP 地址後,點擊解析",
"Role_setting": "權限設定",
"Run": "執行",
"team_tags_set": "團隊標籤",
"Team_Tags": "團隊標籤",
"ai_point_price": "AI 積分計費",
"ai_settings": "AI 設定",
@@ -106,6 +107,7 @@
"no_mcp_tools_list": "暫無數據,需先解析 MCP 地址",
"node_not_intro": "這個節點沒有介紹",
"not_json_file": "請選擇 JSON 檔案",
"not_the_newest": "非最新版",
"oaste_curl_string": "輸入 CURL 代碼",
"open_auto_execute": "啟用自動執行",
"open_vision_function_tip": "有圖示開關的模型即擁有圖片辨識功能。若開啟,模型會解析檔案連結中的圖片,並自動解析使用者問題中的圖片(使用者問題 ≤ 500 字時生效)。",
@@ -138,6 +140,7 @@
"stop_sign_placeholder": "多個序列號透過 | 隔開例如aaa|stop",
"stream_response": "流輸出",
"stream_response_tip": "關閉該開關​​,可以強制模型使用非流模式,並且不會直接進行內容輸出。\n可在 AI 回覆的輸出中,取得本次模型輸出的內容進行二次處理。",
"team_tags_set": "團隊標籤",
"temperature": "溫度",
"temperature_tip": "範圍 010。\n值越大代表模型回答越發散值越小代表回答越嚴謹。",
"template.hard_strict": "嚴格問答範本",

View File

@@ -96,6 +96,7 @@
"add_new_param": "新增參數",
"all_quotes": "全部引用",
"all_result": "完整結果",
"app_not_version": "該應用未發布過,請先發布應用",
"back": "返回",
"base_config": "基本設定",
"bill_already_processed": "訂單已處理",