123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- import type { CredentialFormSchemaNumberInput, CredentialFormSchemaTextInput } from '@/app/components/header/account-setting/model-provider-page/declarations'
- import { type CredentialFormSchema, FormTypeEnum, ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
- import type { ToolVarInputs } from '../../tool/types'
- import ListEmpty from '@/app/components/base/list-empty'
- import { AgentStrategySelector } from './agent-strategy-selector'
- import Link from 'next/link'
- import { useTranslation } from 'react-i18next'
- import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form'
- import { Agent } from '@/app/components/base/icons/src/vender/workflow'
- import { InputNumber } from '@/app/components/base/input-number'
- import Slider from '@/app/components/base/slider'
- import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector'
- import MultipleToolSelector from '@/app/components/plugins/plugin-detail-panel/multiple-tool-selector'
- import Field from './field'
- import { type ComponentProps, memo } from 'react'
- import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
- import Editor from './prompt/editor'
- import { useWorkflowStore } from '../../../store'
- import { useRenderI18nObject } from '@/hooks/use-i18n'
- import type { NodeOutPutVar } from '../../../types'
- import type { Node } from 'reactflow'
- export type Strategy = {
- agent_strategy_provider_name: string
- agent_strategy_name: string
- agent_strategy_label: string
- agent_output_schema: Record<string, any>
- plugin_unique_identifier: string
- }
- export type AgentStrategyProps = {
- strategy?: Strategy
- onStrategyChange: (strategy?: Strategy) => void
- formSchema: CredentialFormSchema[]
- formValue: ToolVarInputs
- onFormValueChange: (value: ToolVarInputs) => void
- nodeOutputVars?: NodeOutPutVar[],
- availableNodes?: Node[],
- nodeId?: string
- }
- type CustomSchema<Type, Field = {}> = Omit<CredentialFormSchema, 'type'> & { type: Type } & Field
- type ToolSelectorSchema = CustomSchema<'tool-selector'>
- type MultipleToolSelectorSchema = CustomSchema<'array[tools]'>
- type CustomField = ToolSelectorSchema | MultipleToolSelectorSchema
- export const AgentStrategy = memo((props: AgentStrategyProps) => {
- const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange, nodeOutputVars, availableNodes, nodeId } = props
- const { t } = useTranslation()
- const defaultModel = useDefaultModel(ModelTypeEnum.textGeneration)
- const renderI18nObject = useRenderI18nObject()
- const workflowStore = useWorkflowStore()
- const {
- setControlPromptEditorRerenderKey,
- } = workflowStore.getState()
- const override: ComponentProps<typeof Form<CustomField>>['override'] = [
- [FormTypeEnum.textNumber, FormTypeEnum.textInput],
- (schema, props) => {
- switch (schema.type) {
- case FormTypeEnum.textInput: {
- const def = schema as CredentialFormSchemaTextInput
- const value = props.value[schema.variable]
- const onChange = (value: string) => {
- props.onChange({ ...props.value, [schema.variable]: value })
- }
- const handleGenerated = (value: string) => {
- onChange(value)
- setControlPromptEditorRerenderKey(Math.random())
- }
- return <Editor
- value={value}
- onChange={onChange}
- onGenerated={handleGenerated}
- title={renderI18nObject(schema.label)}
- headerClassName='bg-transparent px-0 text-text-secondary system-sm-semibold-uppercase'
- containerBackgroundClassName='bg-transparent'
- gradientBorder={false}
- isSupportPromptGenerator={!!def.auto_generate?.type}
- titleTooltip={schema.tooltip && renderI18nObject(schema.tooltip)}
- editorContainerClassName='px-0'
- availableNodes={availableNodes}
- nodesOutputVars={nodeOutputVars}
- isSupportJinja={def.template?.enabled}
- required={def.required}
- varList={[]}
- modelConfig={
- defaultModel.data
- ? {
- mode: 'chat',
- name: defaultModel.data.model,
- provider: defaultModel.data.provider.provider,
- completion_params: {},
- } : undefined
- }
- placeholderClassName='px-2 py-1'
- titleClassName='system-sm-semibold-uppercase text-text-secondary text-[13px]'
- inputClassName='px-2 py-1 bg-components-input-bg-normal focus:bg-components-input-bg-active focus:border-components-input-border-active focus:border rounded-lg'
- />
- }
- case FormTypeEnum.textNumber: {
- const def = schema as CredentialFormSchemaNumberInput
- if (!def.max || !def.min)
- return false
- const defaultValue = schema.default ? Number.parseInt(schema.default) : 1
- const value = props.value[schema.variable] || defaultValue
- const onChange = (value: number) => {
- props.onChange({ ...props.value, [schema.variable]: value })
- }
- return <Field
- title={<>
- {renderI18nObject(def.label)} {def.required && <span className='text-red-500'>*</span>}
- </>}
- tooltip={def.tooltip && renderI18nObject(def.tooltip)}
- inline
- >
- <div className='flex w-[200px] items-center gap-3'>
- <Slider
- value={value}
- onChange={onChange}
- className='w-full'
- min={def.min}
- max={def.max}
- />
- <InputNumber
- value={value}
- // TODO: maybe empty, handle this
- onChange={onChange as any}
- defaultValue={defaultValue}
- size='sm'
- min={def.min}
- max={def.max}
- className='w-12'
- />
- </div>
- </Field>
- }
- }
- },
- ]
- const renderField: ComponentProps<typeof Form<CustomField>>['customRenderField'] = (schema, props) => {
- switch (schema.type) {
- case FormTypeEnum.toolSelector: {
- const value = props.value[schema.variable]
- const onChange = (value: any) => {
- props.onChange({ ...props.value, [schema.variable]: value })
- }
- return (
- <Field
- title={<>
- {renderI18nObject(schema.label)} {schema.required && <span className='text-red-500'>*</span>}
- </>}
- tooltip={schema.tooltip && renderI18nObject(schema.tooltip)}
- >
- <ToolSelector
- nodeId={props.nodeId || ''}
- nodeOutputVars={props.nodeOutputVars || []}
- availableNodes={props.availableNodes || []}
- scope={schema.scope}
- value={value}
- onSelect={item => onChange(item)}
- onDelete={() => onChange(null)}
- />
- </Field>
- )
- }
- case FormTypeEnum.multiToolSelector: {
- const value = props.value[schema.variable]
- const onChange = (value: any) => {
- props.onChange({ ...props.value, [schema.variable]: value })
- }
- return (
- <MultipleToolSelector
- nodeId={props.nodeId || ''}
- nodeOutputVars={props.nodeOutputVars || []}
- availableNodes={props.availableNodes || []}
- scope={schema.scope}
- value={value || []}
- label={renderI18nObject(schema.label)}
- tooltip={schema.tooltip && renderI18nObject(schema.tooltip)}
- onChange={onChange}
- supportCollapse
- required={schema.required}
- />
- )
- }
- }
- }
- return <div className='space-y-2'>
- <AgentStrategySelector value={strategy} onChange={onStrategyChange} />
- {
- strategy
- ? <div>
- <Form<CustomField>
- formSchemas={[
- ...formSchema,
- ]}
- value={formValue}
- onChange={onFormValueChange}
- validating={false}
- showOnVariableMap={{}}
- isEditMode={true}
- isAgentStrategy={true}
- fieldLabelClassName='uppercase'
- customRenderField={renderField}
- override={override}
- nodeId={nodeId}
- nodeOutputVars={nodeOutputVars || []}
- availableNodes={availableNodes || []}
- />
- </div>
- : <ListEmpty
- icon={<Agent className='w-5 h-5 shrink-0 text-text-accent' />}
- title={t('workflow.nodes.agent.strategy.configureTip')}
- description={<div className='text-text-tertiary text-xs'>
- {t('workflow.nodes.agent.strategy.configureTipDesc')} <br />
- <Link href={'/'} className='text-text-accent-secondary'>
- {t('workflow.nodes.agent.learnMore')}
- </Link>
- </div>}
- />
- }
- </div>
- })
- AgentStrategy.displayName = 'AgentStrategy'
|