feat: struct enabled switch

This commit is contained in:
Joel 2025-03-17 14:27:31 +08:00
parent 7fd23d747e
commit b1c5299ff4
7 changed files with 86 additions and 34 deletions

View File

@ -94,7 +94,7 @@ export const useWorkflowVariableType = () => {
}) => { }) => {
// debugger // debugger
const node = getNodes().find(n => n.id === nodeId) const node = getNodes().find(n => n.id === nodeId)
console.log(nodeId, valueSelector) // console.log(nodeId, valueSelector)
const isInIteration = !!node?.data.isInIteration const isInIteration = !!node?.data.isInIteration
const iterationNode = isInIteration ? getNodes().find(n => n.id === node.parentId) : null const iterationNode = isInIteration ? getNodes().find(n => n.id === node.parentId) : null
const availableNodes = getBeforeNodesInSameBranch(nodeId) const availableNodes = getBeforeNodesInSameBranch(nodeId)

View File

@ -4,10 +4,12 @@ import Collapse from '.'
type FieldCollapseProps = { type FieldCollapseProps = {
title: string title: string
children: ReactNode children: ReactNode
operations?: ReactNode
} }
const FieldCollapse = ({ const FieldCollapse = ({
title, title,
children, children,
operations,
}: FieldCollapseProps) => { }: FieldCollapseProps) => {
return ( return (
<div className='py-4'> <div className='py-4'>
@ -15,6 +17,7 @@ const FieldCollapse = ({
trigger={ trigger={
<div className='flex items-center h-6 system-sm-semibold-uppercase text-text-secondary cursor-pointer'>{title}</div> <div className='flex items-center h-6 system-sm-semibold-uppercase text-text-secondary cursor-pointer'>{title}</div>
} }
operations={operations}
> >
<div className='px-4'> <div className='px-4'>
{children} {children}

View File

@ -1,3 +1,4 @@
import type { ReactNode } from 'react'
import { useState } from 'react' import { useState } from 'react'
import { RiArrowDropRightLine } from '@remixicon/react' import { RiArrowDropRightLine } from '@remixicon/react'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
@ -10,6 +11,8 @@ type CollapseProps = {
children: JSX.Element children: JSX.Element
collapsed?: boolean collapsed?: boolean
onCollapse?: (collapsed: boolean) => void onCollapse?: (collapsed: boolean) => void
operations?: ReactNode
} }
const Collapse = ({ const Collapse = ({
disabled, disabled,
@ -17,34 +20,38 @@ const Collapse = ({
children, children,
collapsed, collapsed,
onCollapse, onCollapse,
operations,
}: CollapseProps) => { }: CollapseProps) => {
const [collapsedLocal, setCollapsedLocal] = useState(true) const [collapsedLocal, setCollapsedLocal] = useState(true)
const collapsedMerged = collapsed !== undefined ? collapsed : collapsedLocal const collapsedMerged = collapsed !== undefined ? collapsed : collapsedLocal
return ( return (
<> <>
<div <div className='flex justify-between items-center'>
className='flex items-center' <div
onClick={() => { className='flex items-center'
if (!disabled) { onClick={() => {
setCollapsedLocal(!collapsedMerged) if (!disabled) {
onCollapse?.(!collapsedMerged) setCollapsedLocal(!collapsedMerged)
} onCollapse?.(!collapsedMerged)
}} }
> }}
<div className='shrink-0 w-4 h-4'> >
{ <div className='shrink-0 w-4 h-4'>
!disabled && ( {
<RiArrowDropRightLine !disabled && (
className={cn( <RiArrowDropRightLine
'w-4 h-4 text-text-tertiary', className={cn(
!collapsedMerged && 'transform rotate-90', 'w-4 h-4 text-text-tertiary',
)} !collapsedMerged && 'transform rotate-90',
/> )}
) />
} )
}
</div>
{trigger}
</div> </div>
{trigger} {operations}
</div> </div>
{ {
!collapsedMerged && children !collapsedMerged && children

View File

@ -8,15 +8,20 @@ type Props = {
className?: string className?: string
title?: string title?: string
children: ReactNode children: ReactNode
operations?: ReactNode
} }
const OutputVars: FC<Props> = ({ const OutputVars: FC<Props> = ({
title, title,
children, children,
operations,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<FieldCollapse title={title || t('workflow.nodes.common.outputVars')}> <FieldCollapse
title={title || t('workflow.nodes.common.outputVars')}
operations={operations}
>
{children} {children}
</FieldCollapse> </FieldCollapse>
) )
@ -40,9 +45,11 @@ export const VarItem: FC<VarItemProps> = ({
}) => { }) => {
return ( return (
<div className='py-1'> <div className='py-1'>
<div className='flex leading-[18px] items-center'> <div className='flex justify-between'>
<div className='code-sm-semibold text-text-secondary'>{name}</div> <div className='flex leading-[18px] items-center'>
<div className='ml-2 system-xs-regular text-text-tertiary'>{type}</div> <div className='code-sm-semibold text-text-secondary'>{name}</div>
<div className='ml-2 system-xs-regular text-text-tertiary'>{type}</div>
</div>
</div> </div>
<div className='mt-0.5 system-xs-regular text-text-tertiary'> <div className='mt-0.5 system-xs-regular text-text-tertiary'>
{description} {description}

View File

@ -7,13 +7,16 @@ import type { SchemaRoot, StructuredOutput } from '../types'
import ShowPanel from '@/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/show' import ShowPanel from '@/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/show'
import { useBoolean } from 'ahooks' import { useBoolean } from 'ahooks'
import JsonSchemaConfigModal from './json-schema-config-modal' import JsonSchemaConfigModal from './json-schema-config-modal'
import cn from '@/utils/classnames'
type Props = { type Props = {
className?: string
value?: StructuredOutput value?: StructuredOutput
onChange: (value: StructuredOutput) => void, onChange: (value: StructuredOutput) => void,
} }
const StructureOutput: FC<Props> = ({ const StructureOutput: FC<Props> = ({
className,
value, value,
onChange, onChange,
}) => { }) => {
@ -28,13 +31,18 @@ const StructureOutput: FC<Props> = ({
}) })
}, [onChange]) }, [onChange])
return ( return (
<div> <div className={cn(className)}>
<div className='flex justify-between'> <div className='flex justify-between'>
<div className='flex leading-[18px] items-center'> <div className='flex leading-[18px] items-center'>
<div className='code-sm-semibold text-text-secondary'>structured_output</div> <div className='code-sm-semibold text-text-secondary'>structured_output</div>
<div className='ml-2 system-xs-regular text-text-tertiary'>object</div> <div className='ml-2 system-xs-regular text-text-tertiary'>object</div>
</div> </div>
<Button className='flex' variant='secondary' onClick={showConfigModal}> <Button
size='small'
variant='secondary'
className='flex'
onClick={showConfigModal}
>
<RiEditLine className='size-3.5 mr-1' /> <RiEditLine className='size-3.5 mr-1' />
<div className='system-xs-medium text-components-button-secondary-text'>Configure</div> <div className='system-xs-medium text-components-button-secondary-text'>Configure</div>
</Button> </Button>
@ -43,7 +51,7 @@ const StructureOutput: FC<Props> = ({
<ShowPanel <ShowPanel
payload={value} payload={value}
/>) : ( />) : (
<div className='flex items-center h-10 justify-center rounded-[10px] bg-background-section system-xs-regular text-text-tertiary'>no data</div> <div className='mt-1.5 flex items-center h-10 justify-center rounded-[10px] bg-background-section system-xs-regular text-text-tertiary'>no data</div>
)} )}
{showConfig && ( {showConfig && (

View File

@ -21,6 +21,7 @@ import ResultPanel from '@/app/components/workflow/run/result-panel'
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor' import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
import StructureOutput from './components/structure-output' import StructureOutput from './components/structure-output'
import Switch from '@/app/components/base/switch'
const i18nPrefix = 'workflow.nodes.llm' const i18nPrefix = 'workflow.nodes.llm'
@ -65,6 +66,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
contexts, contexts,
setContexts, setContexts,
runningStatus, runningStatus,
handleStructureOutputEnableChange,
handleStructureOutputChange, handleStructureOutputChange,
handleRun, handleRun,
handleStop, handleStop,
@ -274,17 +276,34 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
/> />
</div> </div>
<Split /> <Split />
<OutputVars> <OutputVars
operations={
<div className='mr-4'>
<Switch
defaultValue={!!inputs.structured_output_enabled}
onChange={handleStructureOutputEnableChange}
size='md'
disabled={readOnly}
/>
</div>
}
>
<> <>
<VarItem <VarItem
name='text' name='text'
type='string' type='string'
description={t(`${i18nPrefix}.outputVars.output`)} description={t(`${i18nPrefix}.outputVars.output`)}
/> />
<StructureOutput {inputs.structured_output_enabled && (
value={inputs.structured_output} <>
onChange={handleStructureOutputChange} <Split className='mt-3' />
/> <StructureOutput
className='mt-4'
value={inputs.structured_output}
onChange={handleStructureOutputChange}
/>
</>
)}
</> </>
</OutputVars> </OutputVars>
{isShowSingleRun && ( {isShowSingleRun && (

View File

@ -277,6 +277,13 @@ const useConfig = (id: string, payload: LLMNodeType) => {
setInputs(newInputs) setInputs(newInputs)
}, [inputs, setInputs]) }, [inputs, setInputs])
const handleStructureOutputEnableChange = useCallback((enabled: boolean) => {
const newInputs = produce(inputs, (draft) => {
draft.structured_output_enabled = enabled
})
setInputs(newInputs)
}, [inputs, setInputs])
const handleStructureOutputChange = useCallback((newOutput: StructuredOutput) => { const handleStructureOutputChange = useCallback((newOutput: StructuredOutput) => {
const newInputs = produce(inputs, (draft) => { const newInputs = produce(inputs, (draft) => {
draft.structured_output = newOutput draft.structured_output = newOutput
@ -416,6 +423,7 @@ const useConfig = (id: string, payload: LLMNodeType) => {
varInputs, varInputs,
runningStatus, runningStatus,
handleStructureOutputChange, handleStructureOutputChange,
handleStructureOutputEnableChange,
handleRun, handleRun,
handleStop, handleStop,
runResult, runResult,