feat(validation): Enhance input validation with 'depends_on' support

- Updated InputValidationBlock to include default values for required fields.
- Implemented validation logic in manager.py to ensure dependent fields are validated based on their dependencies.
This commit is contained in:
abhi1992002
2024-12-02 22:36:11 +05:30
parent 6f144ef77a
commit 20f018b2e5
3 changed files with 80 additions and 29 deletions

View File

@@ -9,11 +9,11 @@ class InputValidationBlock(Block):
class Input(BlockSchema):
required_field: str = SchemaField(
description="parent of dependent_field", default=""
description="parent of dependent_field", default="hello"
)
required_field_2: str = SchemaField(
description="parent of dependent_field", default=""
description="parent of dependent_field"
)
optional_field: str = SchemaField(
@@ -22,7 +22,7 @@ class InputValidationBlock(Block):
dependent_field: str = SchemaField(
description="This field depends on required_field being set",
depends_on=["required_field", "required_field_2"],
default="",
default = ""
)
class Output(BlockSchema):

View File

@@ -421,6 +421,35 @@ def validate_exec(
if not required_fields.issubset(data):
return None, f"{error_prefix} {required_fields - set(data)}"
# Validate dependencies
properties = input_schema.get("properties", {})
for field_name, field_schema in properties.items():
if "depends_on" in field_schema:
dependencies = field_schema["depends_on"]
# Check if dependent field has value
has_value = data.get(field_name) is not None and data.get(field_name) != "" or (field_schema.get("default") is not None and field_schema.get("default") != "")
must_have_value = field_name in required_fields
# Check for missing dependencies when depenedent field is present
missing_deps = [
dep for dep in dependencies
if not data.get(dep) or str(data[dep]).strip() == ""
]
if (has_value or must_have_value) and missing_deps:
return None, f"{error_prefix} Field {field_name} requires {', '.join(missing_deps)} to be set"
# Check if field is required when dependencies are present
has_all_deps = all(
data.get(dep) and str(data[dep]).strip() != ""
for dep in dependencies
)
if has_all_deps and not has_value:
return None, f"{error_prefix} {field_name} is required when {', '.join(dependencies)} are set"
# Last validation: Validate the input values against the schema.
if error := json.validate_with_jsonschema(schema=input_schema, data=data):
error_message = f"{error_prefix} {error}"

View File

@@ -405,33 +405,55 @@ 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`;
}
}
});
}
Object.entries(node.data.inputSchema.properties || {}).forEach(
([key, schema]) => {
if (schema.depends_on) {
const dependencies = schema.depends_on;
// Check if dependent field has value
const hasValue =
(inputData[key] != null &&
String(inputData[key]).trim() !== "") ||
(schema.default != null && String(schema.default).trim() !== "");
const mustHaveValue = node.data.inputSchema.required?.includes(key);
// Check for missing dependencies when dependent field is present
const missingDependencies = dependencies.filter(
(dep) =>
!inputData[dep as keyof typeof inputData] ||
String(inputData[dep as keyof typeof inputData]).trim() === "",
);
if ((hasValue || mustHaveValue) && missingDependencies.length > 0) {
setNestedProperty(
errors,
key,
`Requires ${missingDependencies.join(", ")} to be set`,
);
errorMessage = `Field ${key} requires ${missingDependencies.join(", ")} to be set`;
}
// Check if field is required when dependencies are present
const hasAllDependencies = dependencies.every(
(dep) =>
inputData[dep as keyof typeof inputData] &&
String(inputData[dep as keyof typeof inputData]).trim() !== "",
);
if (hasAllDependencies && !hasValue) {
setNestedProperty(
errors,
key,
`${key} is required when ${dependencies.join(", ")} are set`,
);
errorMessage = `${key} is required when ${dependencies.join(", ")} are set`;
}
}
},
);
// Set errors
setNodes((nodes) => {