mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
feat(validation): Enhance schema validation with 'depends_on' support
- Added 'depends_on' parameter to SchemaField in model.py to specify field dependencies. - Updated useAgentGraph hook to validate input fields based on their dependencies, ensuring required fields are set when dependent fields are filled. - Modified BlockIOSubSchemaMeta to include 'depends_on' as an optional property.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
|
||||
from backend.data.model import SchemaField
|
||||
|
||||
|
||||
class InputValidationBlock(Block):
|
||||
"""
|
||||
TEMPORARY BLOCK FOR TESTING
|
||||
"""
|
||||
|
||||
class Input(BlockSchema):
|
||||
required_field: str = SchemaField(
|
||||
description="parent of dependent_field", default=""
|
||||
)
|
||||
|
||||
required_field_2: str = SchemaField(
|
||||
description="parent of dependent_field", default=""
|
||||
)
|
||||
|
||||
optional_field: str = SchemaField(
|
||||
description="This field is optional", default=""
|
||||
)
|
||||
dependent_field: str = SchemaField(
|
||||
description="This field depends on required_field being set",
|
||||
depends_on=["required_field", "required_field_2"],
|
||||
default="",
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
is_valid: bool = SchemaField(description="Whether the input validation passed")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="a1b2c3d4-e5f6-4a5b-9c8d-7e6f5d4c3b2a",
|
||||
description="Validates input fields based on requirements and dependencies",
|
||||
categories={BlockCategory.BASIC},
|
||||
input_schema=InputValidationBlock.Input,
|
||||
output_schema=InputValidationBlock.Output,
|
||||
)
|
||||
|
||||
def run(self, input_data: Input, **kwargs) -> BlockOutput:
|
||||
if not input_data.required_field or not input_data.required_field_2:
|
||||
yield "is_valid", False
|
||||
return
|
||||
|
||||
if input_data.dependent_field and (not input_data.required_field or not input_data.required_field_2):
|
||||
yield "is_valid", False
|
||||
return
|
||||
|
||||
yield "is_valid", True
|
||||
@@ -124,6 +124,7 @@ def SchemaField(
|
||||
secret: bool = False,
|
||||
exclude: bool = False,
|
||||
hidden: Optional[bool] = None,
|
||||
depends_on: list[str] | None = None,
|
||||
**kwargs,
|
||||
) -> T:
|
||||
json_extra = {
|
||||
@@ -133,6 +134,7 @@ def SchemaField(
|
||||
"secret": secret,
|
||||
"advanced": advanced,
|
||||
"hidden": hidden,
|
||||
"depends_on": depends_on,
|
||||
}.items()
|
||||
if v is not None
|
||||
}
|
||||
|
||||
@@ -366,6 +366,7 @@ export default function useAgentGraph(
|
||||
|
||||
nodes.forEach((node) => {
|
||||
const validate = ajv.compile(node.data.inputSchema);
|
||||
console.log("Validating node", node.id, node.data.inputSchema);
|
||||
const errors = {} as { [key: string]: string };
|
||||
|
||||
// Validate values against schema using AJV
|
||||
@@ -405,7 +406,34 @@ export default function useAgentGraph(
|
||||
setNestedProperty(errors, key, "This field is required");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Object.entries(node.data.inputSchema.properties || {}).forEach(([key, schema]) => {
|
||||
if ('depends_on' in schema) {
|
||||
const dependencies = Array.isArray(schema.depends_on) ? schema.depends_on : [schema.depends_on];
|
||||
|
||||
// Check if dependent field is set while required fields are empty
|
||||
const hasValue = inputData[key as keyof typeof inputData] && String(inputData[key as keyof typeof inputData]).length > 0;
|
||||
const missingDependencies = dependencies.filter(dep => !inputData[dep as keyof typeof inputData] || String(inputData[dep as keyof typeof inputData]).length === 0);
|
||||
|
||||
if (hasValue && missingDependencies.length > 0) {
|
||||
errors[key] = `Requires ${missingDependencies.join(', ')} to be set`;
|
||||
errorMessage = `Field ${key} requires ${missingDependencies.join(', ')} to be set`;
|
||||
}
|
||||
|
||||
// Check if required fields are set but dependent field is empty
|
||||
const hasAllDependencies = dependencies.every(dep =>
|
||||
inputData[dep as keyof typeof inputData] &&
|
||||
String(inputData[dep as keyof typeof inputData]).length > 0
|
||||
);
|
||||
if (hasAllDependencies && (!inputData[key as keyof typeof inputData] || String(inputData[key as keyof typeof inputData]).length === 0)) {
|
||||
errors[key] = `This field is required when ${dependencies.join(', ')} are set`;
|
||||
errorMessage = `${key} is required when ${dependencies.join(', ')} are set`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Set errors
|
||||
setNodes((nodes) => {
|
||||
return nodes.map((n) => {
|
||||
|
||||
@@ -56,6 +56,7 @@ export type BlockIOSubSchemaMeta = {
|
||||
description?: string;
|
||||
placeholder?: string;
|
||||
advanced?: boolean;
|
||||
depends_on?: string[]
|
||||
hidden?: boolean;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user