diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-importer.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-importer.tsx index 16964da140..6ea446d3ae 100644 --- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-importer.tsx +++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-importer.tsx @@ -6,6 +6,8 @@ import { RiClipboardLine, RiCloseLine, RiErrorWarningFill, RiIndentIncrease } fr import copy from 'copy-to-clipboard' import { Editor } from '@monaco-editor/react' import Button from '@/app/components/base/button' +import { checkDepth } from '../../utils' +import { JSON_SCHEMA_MAX_DEPTH } from '@/config' type JsonImporterProps = { onSubmit: (schema: string) => void @@ -71,8 +73,17 @@ const JsonImporter: FC = ({ const handleSubmit = useCallback(() => { try { const parsedJSON = JSON.parse(json) + const maxDepth = checkDepth(parsedJSON) + if (maxDepth > JSON_SCHEMA_MAX_DEPTH) { + setParseError({ + type: 'error', + message: `Schema exceeds maximum depth of ${JSON_SCHEMA_MAX_DEPTH}.`, + }) + return + } onSubmit(parsedJSON) setParseError(null) + setOpen(false) } catch (e: any) { if (e instanceof SyntaxError) diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx index e6ce21b0b8..6a020cec0f 100644 --- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx +++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx @@ -281,6 +281,7 @@ const JsonSchemaConfig: FC = ({ }) useSubscribe('fieldChange', (params) => { + let samePropertyNameError = false const { parentPath, oldFields, fields } = params as ChangeEventParams const newSchema = produce(jsonSchema, (draft) => { const parentSchema = findPropertyWithPath(draft, parentPath) as Field @@ -295,7 +296,7 @@ const JsonSchemaConfig: FC = ({ type: 'error', message: 'Property name already exists', }) - return + samePropertyNameError = true } const newProperties = Object.entries(properties).reduce((acc, [key, value]) => { @@ -384,8 +385,7 @@ const JsonSchemaConfig: FC = ({ type: 'error', message: 'Property name already exists', }) - emit('restorePropertyName') - return + samePropertyNameError = true } const newProperties = Object.entries(properties).reduce((acc, [key, value]) => { @@ -463,6 +463,7 @@ const JsonSchemaConfig: FC = ({ schema.enum = fields.enum } }) + if (samePropertyNameError) return setJsonSchema(newSchema) emit('fieldChangeSuccess') }) diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/index.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/index.tsx index f2c129131d..7e6fd8ec93 100644 --- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/index.tsx +++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/edit-card/index.tsx @@ -14,6 +14,7 @@ import { useJsonSchemaConfigStore } from '../../store' import { useMittContext } from '../../context' import produce from 'immer' import { useUnmount } from 'ahooks' +import { JSON_SCHEMA_MAX_DEPTH } from '@/config' export type EditData = { name: string @@ -46,8 +47,6 @@ const TYPE_OPTIONS = [ { value: ArrayType.object, text: 'array[object]' }, ] -const DEPTH_LIMIT = 10 - const EditCard: FC = ({ fields, depth, @@ -64,7 +63,7 @@ const EditCard: FC = ({ const { emit, useSubscribe } = useMittContext() const blurWithActions = useRef(false) - const disableAddBtn = fields.type !== Type.object && fields.type !== ArrayType.object && depth < DEPTH_LIMIT + const disableAddBtn = depth >= JSON_SCHEMA_MAX_DEPTH || (fields.type !== Type.object && fields.type !== ArrayType.object) const hasAdvancedOptions = fields.type === Type.string || fields.type === Type.number const isAdvancedEditing = advancedEditing || isAddingNewField diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/index.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/index.tsx index 6468935aa2..425146039e 100644 --- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/index.tsx +++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/index.tsx @@ -16,7 +16,7 @@ const VisualEditor: FC = ({ schema={schema} required={false} path={[]} - depth={0} + depth={1} /> ) diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/schema-node.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/schema-node.tsx index 85c08df17d..aa3d57a507 100644 --- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/schema-node.tsx +++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/visual-editor/schema-node.tsx @@ -10,6 +10,7 @@ import Card from './card' import { useJsonSchemaConfigStore } from '../store' import { useDebounceFn } from 'ahooks' import AddField from './add-field' +import { JSON_SCHEMA_MAX_DEPTH } from '@/config' type SchemaNodeProps = { name: string @@ -22,28 +23,28 @@ type SchemaNodeProps = { // Support 10 levels of indentation const indentPadding: Record = { - 0: 'pl-0', - 1: 'pl-[20px]', - 2: 'pl-[40px]', - 3: 'pl-[60px]', - 4: 'pl-[80px]', - 5: 'pl-[100px]', - 6: 'pl-[120px]', - 7: 'pl-[140px]', - 8: 'pl-[160px]', - 9: 'pl-[180px]', + 1: 'pl-0', + 2: 'pl-[20px]', + 3: 'pl-[40px]', + 4: 'pl-[60px]', + 5: 'pl-[80px]', + 6: 'pl-[100px]', + 7: 'pl-[120px]', + 8: 'pl-[140px]', + 9: 'pl-[160px]', + 10: 'pl-[180px]', } const indentLeft: Record = { - 1: 'left-0', - 2: 'left-[20px]', - 3: 'left-[40px]', - 4: 'left-[60px]', - 5: 'left-[80px]', - 6: 'left-[100px]', - 7: 'left-[120px]', - 8: 'left-[140px]', - 9: 'left-[160px]', + 2: 'left-0', + 3: 'left-[20px]', + 4: 'left-[40px]', + 5: 'left-[60px]', + 6: 'left-[80px]', + 7: 'left-[100px]', + 8: 'left-[120px]', + 9: 'left-[140px]', + 10: 'left-[160px]', } const SchemaNode: FC = ({ @@ -66,7 +67,7 @@ const SchemaNode: FC = ({ const hasChildren = getHasChildren(schema) const type = getFieldType(schema) - const isHovering = hoveringProperty === path.join('.') && depth > 0 + const isHovering = hoveringProperty === path.join('.') && depth > 1 const handleExpand = () => { setIsExpanded(!isExpanded) @@ -85,7 +86,7 @@ const SchemaNode: FC = ({ return (
- {depth > 0 && hasChildren && ( + {depth > 1 && hasChildren && (
= ({
- {isExpanded && hasChildren && ( + {isExpanded && hasChildren && depth < JSON_SCHEMA_MAX_DEPTH && ( <> {schema.type === Type.object && schema.properties && ( Object.entries(schema.properties).map(([key, childSchema]) => ( @@ -176,7 +177,7 @@ const SchemaNode: FC = ({ )} { - depth === 0 && !isAddingNewField && ( + depth === 1 && !isAddingNewField && ( ) } diff --git a/web/app/components/workflow/nodes/llm/utils.ts b/web/app/components/workflow/nodes/llm/utils.ts index e8930dc13e..f0184b0738 100644 --- a/web/app/components/workflow/nodes/llm/utils.ts +++ b/web/app/components/workflow/nodes/llm/utils.ts @@ -32,12 +32,12 @@ export const inferType = (value: any): Type => { return Type.string } -export function jsonToSchema(json: any): Field { +export const jsonToSchema = (json: any): Field => { const schema: Field = { type: inferType(json), } - if (schema.type === 'object') { + if (schema.type === Type.object) { schema.properties = {} schema.required = [] schema.additionalProperties = false @@ -53,3 +53,22 @@ export function jsonToSchema(json: any): Field { return schema } + +export const checkDepth = (json: any, currentDepth = 1) => { + const type = inferType(json) + if (type !== Type.object && type !== Type.array) + return currentDepth + + let maxDepth = currentDepth + if (type === Type.object) { + Object.keys(json).forEach((key) => { + const depth = checkDepth(json[key], currentDepth + 1) + maxDepth = Math.max(maxDepth, depth) + }) + } + else if (type === Type.array && json.length > 0) { + const depth = checkDepth(json[0], currentDepth + 1) + maxDepth = Math.max(maxDepth, depth) + } + return maxDepth +} diff --git a/web/config/index.ts b/web/config/index.ts index 5600022ba1..6d1cd554f8 100644 --- a/web/config/index.ts +++ b/web/config/index.ts @@ -276,3 +276,5 @@ export const GITHUB_ACCESS_TOKEN = process.env.NEXT_PUBLIC_GITHUB_ACCESS_TOKEN | export const SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS = '.difypkg,.difybndl' export const FULL_DOC_PREVIEW_LENGTH = 50 + +export const JSON_SCHEMA_MAX_DEPTH = 10