import type { Memory, Var } from '../../types' import type { ToolVarInputs } from '../tool/types' import type { AgentNodeType } from './types' import { produce } from 'immer' import { useCallback, useEffect, useMemo } from 'react' import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' import { generateAgentToolValue, toolParametersToFormSchemas, } from '@/app/components/tools/utils/to-form-schema' import { useIsChatMode, useNodesReadOnly } from '@/app/components/workflow/hooks' import { useCheckInstalled, useFetchPluginsInMarketPlaceByIds } from '@/service/use-plugins' import { useStrategyProviderDetail } from '@/service/use-strategy' import { VarType as VarKindType } from '../../types' import useAvailableVarList from '../_base/hooks/use-available-var-list' import useNodeCrud from '../_base/hooks/use-node-crud' import useVarList from '../_base/hooks/use-var-list' import { VarType } from '../tool/types' type StrategyStatus = { plugin: { source: 'external' | 'marketplace' installed: boolean } isExistInPlugin: boolean } export const useStrategyInfo = (strategyProviderName?: string, strategyName?: string) => { const strategyProvider = useStrategyProviderDetail(strategyProviderName || '', { retry: false }) const strategy = strategyProvider.data?.declaration.strategies.find( (str) => str.identity.name === strategyName, ) const marketplace = useFetchPluginsInMarketPlaceByIds([strategyProviderName!], { retry: false, }) const strategyStatus: StrategyStatus | undefined = useMemo(() => { if (strategyProvider.isLoading || marketplace.isLoading) return undefined const strategyExist = !!strategy const isPluginInstalled = !strategyProvider.isError const isInMarketplace = !!marketplace.data?.data.plugins.at(0) return { plugin: { source: isInMarketplace ? 'marketplace' : 'external', installed: isPluginInstalled, }, isExistInPlugin: strategyExist, } }, [strategy, marketplace, strategyProvider.isError, strategyProvider.isLoading]) const refetch = useCallback(() => { strategyProvider.refetch() marketplace.refetch() }, [marketplace, strategyProvider]) return { strategyProvider, strategy, strategyStatus, refetch, } } const useConfig = (id: string, payload: AgentNodeType) => { const { nodesReadOnly: readOnly } = useNodesReadOnly() const { inputs, setInputs } = useNodeCrud(id, payload) // variables const { handleVarListChange, handleAddVariable } = useVarList({ inputs, setInputs, }) const { strategyStatus: currentStrategyStatus, strategy: currentStrategy, strategyProvider, } = useStrategyInfo(inputs.agent_strategy_provider_name, inputs.agent_strategy_name) const pluginId = inputs.agent_strategy_provider_name?.split('/').splice(0, 2).join('/') const pluginDetail = useCheckInstalled({ pluginIds: [pluginId!], enabled: Boolean(pluginId), }) const formData = useMemo(() => { const paramNameList = (currentStrategy?.parameters || []).map((item) => item.name) const res = Object.fromEntries( Object.entries(inputs.agent_parameters || {}) .filter(([name]) => paramNameList.includes(name)) .map(([key, value]) => { return [key, value.value] }), ) return res }, [inputs.agent_parameters, currentStrategy?.parameters]) const getParamVarType = useCallback( (paramName: string) => { const isVariable = currentStrategy?.parameters.some( (param) => param.name === paramName && param.type === FormTypeEnum.any, ) if (isVariable) return VarType.variable return VarType.constant }, [currentStrategy?.parameters], ) const onFormChange = (value: Record) => { const res: ToolVarInputs = {} Object.entries(value).forEach(([key, val]) => { res[key] = { type: getParamVarType(key), value: val, } }) setInputs({ ...inputs, agent_parameters: res, }) } const formattingToolData = (data: any) => { const settingValues = generateAgentToolValue( data.settings, toolParametersToFormSchemas( data.schemas.filter((param: { form: string }) => param.form !== 'llm') as any, ), ) const paramValues = generateAgentToolValue( data.parameters, toolParametersToFormSchemas( data.schemas.filter((param: { form: string }) => param.form === 'llm') as any, ), true, ) const res = produce(data, (draft: any) => { draft.settings = settingValues draft.parameters = paramValues }) return res } const formattingLegacyData = () => { if (inputs.version || inputs.tool_node_version) return inputs const newData = produce(inputs, (draft) => { const schemas = currentStrategy?.parameters || [] Object.keys(draft.agent_parameters || {}).forEach((key) => { const targetSchema = schemas.find((schema) => schema.name === key) if (targetSchema?.type === FormTypeEnum.toolSelector) draft.agent_parameters![key]!.value = formattingToolData( draft.agent_parameters![key]!.value, ) if (targetSchema?.type === FormTypeEnum.multiToolSelector) draft.agent_parameters![key]!.value = draft.agent_parameters![key]!.value.map( (tool: any) => formattingToolData(tool), ) }) draft.tool_node_version = '2' }) return newData } // formatting legacy data useEffect(() => { if (!currentStrategy) return const newData = formattingLegacyData() setInputs(newData) }, [currentStrategy]) // vars const filterMemoryPromptVar = useCallback((varPayload: Var) => { return [ VarKindType.arrayObject, VarKindType.array, VarKindType.number, VarKindType.string, VarKindType.secret, VarKindType.arrayString, VarKindType.arrayNumber, VarKindType.file, VarKindType.arrayFile, ].includes(varPayload.type) }, []) const { availableVars, availableNodesWithParent } = useAvailableVarList(id, { onlyLeafNodeVar: false, filterVar: filterMemoryPromptVar, }) // single run const outputSchema = useMemo(() => { const res: any[] = [] if (!inputs.output_schema || !inputs.output_schema.properties) return [] Object.keys(inputs.output_schema.properties).forEach((outputKey) => { const output = inputs.output_schema.properties[outputKey] res.push({ name: outputKey, type: output.type === 'array' ? `Array[${output.items?.type ? output.items.type.slice(0, 1).toLocaleUpperCase() + output.items.type.slice(1) : 'Unknown'}]` : `${output.type ? output.type.slice(0, 1).toLocaleUpperCase() + output.type.slice(1) : 'Unknown'}`, description: output.description, }) }) return res }, [inputs.output_schema]) const handleMemoryChange = useCallback( (newMemory?: Memory) => { const newInputs = produce(inputs, (draft) => { draft.memory = newMemory }) setInputs(newInputs) }, [inputs, setInputs], ) const isChatMode = useIsChatMode() return { readOnly, inputs, setInputs, handleVarListChange, handleAddVariable, currentStrategy, formData, onFormChange, currentStrategyStatus, strategyProvider: strategyProvider.data, pluginDetail: pluginDetail.data?.plugins.at(0), availableVars, availableNodesWithParent, outputSchema, handleMemoryChange, isChatMode, } } export default useConfig