feat: integrate editor

This commit is contained in:
Joel 2025-03-17 11:45:18 +08:00
parent 7ea0a972d5
commit 7fd23d747e
5 changed files with 78 additions and 2 deletions

View File

@ -665,7 +665,7 @@ export const getVarType = ({
if (!targetVar) if (!targetVar)
return VarType.string return VarType.string
const isStructuredOutputVar = !!targetVar.children.schema?.properties const isStructuredOutputVar = !!targetVar.children?.schema?.properties
if (isStructuredOutputVar) { if (isStructuredOutputVar) {
let currProperties = targetVar.children.schema; let currProperties = targetVar.children.schema;
(valueSelector as ValueSelector).slice(2).forEach((key, i) => { (valueSelector as ValueSelector).slice(2).forEach((key, i) => {

View File

@ -0,0 +1,60 @@
'use client'
import Button from '@/app/components/base/button'
import { RiEditLine } from '@remixicon/react'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import type { SchemaRoot, StructuredOutput } from '../types'
import ShowPanel from '@/app/components/workflow/nodes/_base/components/variable/object-child-tree-panel/show'
import { useBoolean } from 'ahooks'
import JsonSchemaConfigModal from './json-schema-config-modal'
type Props = {
value?: StructuredOutput
onChange: (value: StructuredOutput) => void,
}
const StructureOutput: FC<Props> = ({
value,
onChange,
}) => {
const [showConfig, {
setTrue: showConfigModal,
setFalse: hideConfigModal,
}] = useBoolean(false)
const handleChange = useCallback((value: SchemaRoot) => {
onChange({
schema: value,
})
}, [onChange])
return (
<div>
<div className='flex justify-between'>
<div className='flex leading-[18px] items-center'>
<div className='code-sm-semibold text-text-secondary'>structured_output</div>
<div className='ml-2 system-xs-regular text-text-tertiary'>object</div>
</div>
<Button className='flex' variant='secondary' onClick={showConfigModal}>
<RiEditLine className='size-3.5 mr-1' />
<div className='system-xs-medium text-components-button-secondary-text'>Configure</div>
</Button>
</div>
{value?.schema ? (
<ShowPanel
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>
)}
{showConfig && (
<JsonSchemaConfigModal
isShow
defaultSchema={(value?.schema || {}) as any} // wait for types change
onSave={handleChange as any} // wait for types change
onClose={hideConfigModal}
/>
)}
</div>
)
}
export default React.memo(StructureOutput)

View File

@ -20,6 +20,7 @@ import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/c
import ResultPanel from '@/app/components/workflow/run/result-panel' 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'
const i18nPrefix = 'workflow.nodes.llm' const i18nPrefix = 'workflow.nodes.llm'
@ -64,6 +65,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
contexts, contexts,
setContexts, setContexts,
runningStatus, runningStatus,
handleStructureOutputChange,
handleRun, handleRun,
handleStop, handleStop,
varInputs, varInputs,
@ -279,6 +281,10 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
type='string' type='string'
description={t(`${i18nPrefix}.outputVars.output`)} description={t(`${i18nPrefix}.outputVars.output`)}
/> />
<StructureOutput
value={inputs.structured_output}
onChange={handleStructureOutputChange}
/>
</> </>
</OutputVars> </OutputVars>
{isShowSingleRun && ( {isShowSingleRun && (

View File

@ -15,6 +15,8 @@ export type LLMNodeType = CommonNodeType & {
enabled: boolean enabled: boolean
configs?: VisionSetting configs?: VisionSetting
} }
structured_output_enabled?: boolean
structured_output?: StructuredOutput
} }
export enum Type { export enum Type {

View File

@ -9,7 +9,7 @@ import {
} from '../../hooks' } from '../../hooks'
import useAvailableVarList from '../_base/hooks/use-available-var-list' import useAvailableVarList from '../_base/hooks/use-available-var-list'
import useConfigVision from '../../hooks/use-config-vision' import useConfigVision from '../../hooks/use-config-vision'
import type { LLMNodeType } from './types' import type { LLMNodeType, StructuredOutput } from './types'
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { import {
ModelTypeEnum, ModelTypeEnum,
@ -277,6 +277,13 @@ const useConfig = (id: string, payload: LLMNodeType) => {
setInputs(newInputs) setInputs(newInputs)
}, [inputs, setInputs]) }, [inputs, setInputs])
const handleStructureOutputChange = useCallback((newOutput: StructuredOutput) => {
const newInputs = produce(inputs, (draft) => {
draft.structured_output = newOutput
})
setInputs(newInputs)
}, [inputs, setInputs])
const filterInputVar = useCallback((varPayload: Var) => { const filterInputVar = useCallback((varPayload: Var) => {
return [VarType.number, VarType.string, VarType.secret, VarType.arrayString, VarType.arrayNumber, VarType.file, VarType.arrayFile].includes(varPayload.type) return [VarType.number, VarType.string, VarType.secret, VarType.arrayString, VarType.arrayNumber, VarType.file, VarType.arrayFile].includes(varPayload.type)
}, []) }, [])
@ -408,6 +415,7 @@ const useConfig = (id: string, payload: LLMNodeType) => {
setContexts, setContexts,
varInputs, varInputs,
runningStatus, runningStatus,
handleStructureOutputChange,
handleRun, handleRun,
handleStop, handleStop,
runResult, runResult,