-
Notifications
You must be signed in to change notification settings - Fork 843
Add basic validation function in python #624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a new validation layer for A2UI JSON payloads, which is a great addition to ensure data integrity beyond basic schema validation. The new validation.py module is well-structured and includes checks for component integrity, topology (cycles, orphans), recursion depth, and path syntax. The accompanying test suite in test_validation.py is comprehensive and covers many important edge cases.
My feedback includes a critical point about silent error handling that could lead to validation being skipped, and a suggestion to improve maintainability by refactoring hardcoded values into constants. Overall, this is a solid contribution that significantly improves the robustness of A2UI message processing.
| except Exception: | ||
| # If schema traversal fails, return empty map | ||
| pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a broad except Exception: with a pass is dangerous. It will silently swallow any errors that occur during schema parsing (e.g., due to an unexpected schema structure), resulting in an empty ref_map. This effectively disables all component reference validation without any warning, which could allow invalid JSON to pass through. At a minimum, this should log a warning to indicate that reference validation was skipped. A better approach would be to handle more specific exceptions related to key/index errors during dictionary traversal.
| if global_depth > 50: | ||
| raise ValueError("Global recursion limit exceeded: Depth > 50") | ||
|
|
||
| if isinstance(item, list): | ||
| for x in item: | ||
| traverse(x, global_depth + 1, func_depth) | ||
| return | ||
|
|
||
| if isinstance(item, dict): | ||
| # Check for path | ||
| if PATH in item and isinstance(item[PATH], str): | ||
| path = item[PATH] | ||
| if not re.fullmatch(JSON_POINTER_PATTERN, path): | ||
| raise ValueError(f"Invalid JSON Pointer syntax: '{path}'") | ||
|
|
||
| # Check for FunctionCall | ||
| is_func = CALL in item and ARGS in item | ||
|
|
||
| if is_func: | ||
| if func_depth >= 5: | ||
| raise ValueError(f"Recursion limit exceeded: {FUNCTION_CALL} depth > 5") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The recursion depth limits (50 for global, 5 for function calls) are hardcoded as magic numbers. To improve readability and maintainability, it's better to define these as module-level constants (e.g., MAX_GLOBAL_DEPTH = 50, MAX_FUNC_CALL_DEPTH = 5). This makes their purpose clear and allows them to be easily located and modified in one place.
| 1. **JSON Schema Validation**: Ensures payload adheres to the A2UI schema. | ||
| 2. **Component Integrity**: | ||
| - All component IDs are unique. | ||
| - A 'root' component exists. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the updateComponents message only include a partial list of components to update an existing surface, does it also require a root component?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we only enforce the root requirement if there is a CreateSurface message along with the UpdateComponents message?
|
|
||
| a2ui_schema = await self.get_a2ui_schema(tool_context) | ||
| jsonschema.validate(instance=a2ui_json_payload, schema=a2ui_schema) | ||
| validate_a2ui_json(a2ui_json_payload, a2ui_schema) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the expected format of the a2ui_schema?
v0.9 is a modularized version with multiple schemas. Do we need to bundle them into a unified one?
#557 adds an A2uiValidator that builds referencing registry to work with multiple schemas: https://github.com/nan-yu/A2UI/blob/836b2858833516ec532fdaa5366e0c4f386c72ad/a2a_agents/python/a2ui_agent/src/a2ui/inference/schema/validator.py. I think we can move these additional validations into the A2uiValidator.
The send_a2ui_to_client_toolset.py will extract the A2uiCatalog instance stored in the session and invoke the validator to validate the json payload, for example, f350823#diff-5f858e097e91850cde41d939245f10a3ef616ec3875236afcb4cfa4105f4384aR279.
To cover common errors not covered by the json schema