mirror of
https://github.com/langgenius/dify.git
synced 2026-04-15 01:38:19 +08:00
Merge branch 'feat/plugins' of https://github.com/langgenius/dify into feat/plugins
This commit is contained in:
commit
67019d128b
@ -39,7 +39,12 @@ type FormProps<
|
||||
inputClassName?: string
|
||||
isShowDefaultValue?: boolean
|
||||
fieldMoreInfo?: (payload: CredentialFormSchema | CustomFormSchema) => ReactNode
|
||||
customRenderField?: (formSchema: CustomFormSchema, props: FormProps<CustomFormSchema>) => ReactNode
|
||||
customRenderField?: (
|
||||
formSchema: CustomFormSchema,
|
||||
props: Omit<FormProps<CustomFormSchema>, 'override' | 'customRenderField'>
|
||||
) => ReactNode
|
||||
// If return falsy value, this field will fallback to default render
|
||||
override?: [Array<FormTypeEnum>, (formSchema: CredentialFormSchema) => ReactNode]
|
||||
}
|
||||
|
||||
function Form<
|
||||
@ -60,6 +65,7 @@ function Form<
|
||||
isShowDefaultValue = false,
|
||||
fieldMoreInfo,
|
||||
customRenderField,
|
||||
override,
|
||||
}: FormProps<CustomFormSchema>) {
|
||||
const language = useLanguage()
|
||||
const [changeKey, setChangeKey] = useState('')
|
||||
@ -97,6 +103,15 @@ function Form<
|
||||
triggerClassName='ml-1 w-4 h-4'
|
||||
asChild={false} />
|
||||
))
|
||||
if (override) {
|
||||
const [overrideTypes, overrideRender] = override
|
||||
if (overrideTypes.includes(formSchema.type as FormTypeEnum)) {
|
||||
const node = overrideRender(formSchema as CredentialFormSchema)
|
||||
if (node)
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
if (formSchema.type === FormTypeEnum.textInput || formSchema.type === FormTypeEnum.secretInput || formSchema.type === FormTypeEnum.textNumber) {
|
||||
const {
|
||||
variable, label, placeholder, required, show_on,
|
||||
@ -343,7 +358,6 @@ function Form<
|
||||
inputClassName,
|
||||
isShowDefaultValue,
|
||||
fieldMoreInfo,
|
||||
customRenderField,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,6 @@ function formatStrategy(input: StrategyPluginDetail[], getIcon: (i: string) => s
|
||||
return input.map((item) => {
|
||||
const res: ToolWithProvider = {
|
||||
id: item.provider,
|
||||
// TODO: replace this
|
||||
author: item.declaration.identity.author,
|
||||
name: item.declaration.identity.name,
|
||||
description: item.declaration.identity.description as any,
|
||||
|
||||
@ -35,6 +35,87 @@ type MultipleToolSelectorSchema = CustomSchema<'array[tools]'>
|
||||
|
||||
type CustomField = MaxIterFormSchema | ToolSelectorSchema | MultipleToolSelectorSchema
|
||||
|
||||
const devMockForm = [{
|
||||
name: 'model',
|
||||
label: {
|
||||
en_US: 'Model',
|
||||
zh_Hans: '模型',
|
||||
pt_BR: 'Model',
|
||||
ja_JP: 'Model',
|
||||
},
|
||||
placeholder: null,
|
||||
scope: 'tool-call&llm',
|
||||
auto_generate: null,
|
||||
template: null,
|
||||
required: true,
|
||||
default: null,
|
||||
min: null,
|
||||
max: null,
|
||||
options: [],
|
||||
type: 'model-selector',
|
||||
},
|
||||
{
|
||||
name: 'tools',
|
||||
label: {
|
||||
en_US: 'Tools list',
|
||||
zh_Hans: '工具列表',
|
||||
pt_BR: 'Tools list',
|
||||
ja_JP: 'Tools list',
|
||||
},
|
||||
placeholder: null,
|
||||
scope: null,
|
||||
auto_generate: null,
|
||||
template: null,
|
||||
required: true,
|
||||
default: null,
|
||||
min: null,
|
||||
max: null,
|
||||
options: [],
|
||||
type: 'array[tools]',
|
||||
},
|
||||
{
|
||||
name: 'instruction',
|
||||
label: {
|
||||
en_US: 'Instruction',
|
||||
zh_Hans: '指令',
|
||||
pt_BR: 'Instruction',
|
||||
ja_JP: 'Instruction',
|
||||
},
|
||||
placeholder: null,
|
||||
scope: null,
|
||||
auto_generate: {
|
||||
type: 'prompt_instruction',
|
||||
},
|
||||
template: {
|
||||
enabled: true,
|
||||
},
|
||||
required: true,
|
||||
default: null,
|
||||
min: null,
|
||||
max: null,
|
||||
options: [],
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
name: 'query',
|
||||
label: {
|
||||
en_US: 'Query',
|
||||
zh_Hans: '查询',
|
||||
pt_BR: 'Query',
|
||||
ja_JP: 'Query',
|
||||
},
|
||||
placeholder: null,
|
||||
scope: null,
|
||||
auto_generate: null,
|
||||
template: null,
|
||||
required: true,
|
||||
default: null,
|
||||
min: null,
|
||||
max: null,
|
||||
options: [],
|
||||
type: 'string',
|
||||
}]
|
||||
|
||||
export const AgentStrategy = (props: AgentStrategyProps) => {
|
||||
const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange } = props
|
||||
const { t } = useTranslation()
|
||||
@ -84,7 +165,6 @@ export const AgentStrategy = (props: AgentStrategyProps) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(formSchema)
|
||||
return <div className='space-y-2'>
|
||||
<AgentStrategySelector value={strategy} onChange={onStrategyChange} />
|
||||
{
|
||||
@ -93,18 +173,7 @@ export const AgentStrategy = (props: AgentStrategyProps) => {
|
||||
<Form<CustomField>
|
||||
formSchemas={[
|
||||
...formSchema,
|
||||
{
|
||||
type: 'max-iter',
|
||||
variable: 'max_iterations',
|
||||
label: {
|
||||
en_US: 'Max Iterations',
|
||||
zh_Hans: '最大迭代次数',
|
||||
},
|
||||
name: 'max iter',
|
||||
required: true,
|
||||
show_on: [],
|
||||
default: '3',
|
||||
} as MaxIterFormSchema,
|
||||
...devMockForm as any,
|
||||
]}
|
||||
value={formValue}
|
||||
onChange={onFormValueChange}
|
||||
|
||||
@ -32,6 +32,7 @@ import {
|
||||
} from '@/app/components/workflow/constants'
|
||||
import type { PromptItem } from '@/models/debug'
|
||||
import { VAR_REGEX } from '@/config'
|
||||
import type { AgentNodeType } from '../../../agent/types'
|
||||
|
||||
export const isSystemVar = (valueSelector: ValueSelector) => {
|
||||
return valueSelector[0] === 'sys' || valueSelector[1] === 'sys'
|
||||
@ -316,7 +317,18 @@ const formatItem = (
|
||||
}
|
||||
|
||||
case BlockEnum.Agent: {
|
||||
res.vars = []
|
||||
const payload = data as AgentNodeType
|
||||
if (!payload.agent_parameters) {
|
||||
res.vars = []
|
||||
break
|
||||
}
|
||||
res.vars = Object.keys(payload.agent_parameters).map((key) => {
|
||||
return {
|
||||
variable: key,
|
||||
// TODO: is this correct?
|
||||
type: payload.agent_parameters![key].type as unknown as VarType,
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
@ -789,6 +801,14 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => {
|
||||
res = [(data as ListFilterNodeType).variable]
|
||||
break
|
||||
}
|
||||
|
||||
case BlockEnum.Agent: {
|
||||
const payload = data as AgentNodeType
|
||||
const params = payload.agent_parameters || {}
|
||||
const mixVars = matchNotSystemVars(Object.keys(params)?.filter(key => params[key].type === ToolVarType.mixed).map(key => params[key].value) as string[])
|
||||
const vars = Object.keys(params).filter(key => params[key].type === ToolVarType.variable).map(key => params[key].value as string) || []
|
||||
res = [...(mixVars as ValueSelector[]), ...(vars as any)]
|
||||
}
|
||||
}
|
||||
return res || []
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ const nodeDefault: NodeDefault<AgentNodeType> = {
|
||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
||||
: ALL_COMPLETION_AVAILABLE_BLOCKS
|
||||
},
|
||||
checkValid(payload) {
|
||||
checkValid(payload, t, moreDataForCheckValid) {
|
||||
let isValid = true
|
||||
let errorMessages = ''
|
||||
if (payload.type) {
|
||||
|
||||
@ -1,16 +1,42 @@
|
||||
import type { FC } from 'react'
|
||||
import { type FC, useMemo } from 'react'
|
||||
import type { NodeProps } from '../../types'
|
||||
import type { AgentNodeType } from './types'
|
||||
import { SettingItem } from '../_base/components/setting-item'
|
||||
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
|
||||
import { Group, GroupLabel } from '../_base/components/group'
|
||||
import type { ToolIconProps } from './components/tool-icon'
|
||||
import { ToolIcon } from './components/tool-icon'
|
||||
import useConfig from './use-config'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useInstalledPluginList } from '@/service/use-plugins'
|
||||
|
||||
const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
|
||||
const { inputs } = useConfig(props.id, props.data)
|
||||
const { inputs, currentStrategy } = useConfig(props.id, props.data)
|
||||
const { t } = useTranslation()
|
||||
const pluginList = useInstalledPluginList()
|
||||
// TODO: Implement models
|
||||
const models = useMemo(() => {
|
||||
const models = []
|
||||
// if selected, show in node
|
||||
// if required and not selected, show empty selector
|
||||
// if not required and not selected, show nothing
|
||||
}, [currentStrategy, inputs.agent_parameters])
|
||||
|
||||
const tools = useMemo(() => {
|
||||
const tools: Array<ToolIconProps> = []
|
||||
currentStrategy?.parameters.forEach((param) => {
|
||||
if (['array[tool]', 'tool'].includes(param.type)) {
|
||||
const vari = inputs.agent_parameters?.[param.name]
|
||||
if (!vari) return
|
||||
if (Array.isArray(vari.value)) {
|
||||
// TODO: Implement array of tools
|
||||
}
|
||||
else {
|
||||
// TODO: Implement single tool
|
||||
}
|
||||
}
|
||||
})
|
||||
}, [currentStrategy, inputs.agent_parameters])
|
||||
return <div className='mb-1 px-3 py-1 space-y-1'>
|
||||
{inputs.agent_strategy_name
|
||||
? <SettingItem
|
||||
|
||||
@ -1,6 +1,16 @@
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import type { NodeTracing } from '@/types/workflow'
|
||||
|
||||
function printNodeStructure(node: NodeTracing, level: number) {
|
||||
const indent = ' '.repeat(level)
|
||||
console.log(`${indent}${node.title}`)
|
||||
if (node.parallelDetail?.children) {
|
||||
node.parallelDetail.children.forEach((child) => {
|
||||
printNodeStructure(child, level + 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function addTitle({
|
||||
list, level, parallelNumRecord,
|
||||
}: {
|
||||
@ -52,6 +62,7 @@ function addTitle({
|
||||
|
||||
// list => group by parallel_id(parallel tree).
|
||||
const format = (list: NodeTracing[], t: any): NodeTracing[] => {
|
||||
// console.log(list)
|
||||
const result: NodeTracing[] = [...list]
|
||||
const parallelFirstNodeMap: Record<string, string> = {}
|
||||
// list to tree by parent_parallel_start_node_id and parallel_start_node_id
|
||||
@ -65,7 +76,7 @@ const format = (list: NodeTracing[], t: any): NodeTracing[] => {
|
||||
|
||||
const isParallelStartNode = !parallelFirstNodeMap[parallel_id]
|
||||
if (isParallelStartNode) {
|
||||
const selfNode = { ...node }
|
||||
const selfNode = { ...node, parallelDetail: undefined }
|
||||
node.parallelDetail = {
|
||||
isParallelStartNode: true,
|
||||
children: [selfNode],
|
||||
@ -86,6 +97,7 @@ const format = (list: NodeTracing[], t: any): NodeTracing[] => {
|
||||
if (parentParallelStartNode!.parallelDetail.children)
|
||||
parentParallelStartNode!.parallelDetail.children.push(node)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// append to parallel start node
|
||||
@ -112,6 +124,11 @@ const format = (list: NodeTracing[], t: any): NodeTracing[] => {
|
||||
return true
|
||||
})
|
||||
|
||||
// print node structure for debug
|
||||
filteredInParallelSubNodes.forEach((node) => {
|
||||
printNodeStructure(node, 0)
|
||||
})
|
||||
|
||||
const parallelNumRecord: Record<string, number> = {
|
||||
num: 0,
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user