-
Notifications
You must be signed in to change notification settings - Fork 810
Refactor FunctionCall to enable full validation #551
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?
Changes from all commits
f7d496e
5d9bef1
772684c
4836a06
23d24d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| # Extending A2UI with Custom Functions | ||
|
|
||
| A2UI functions are designed to be extensible. Third-party developers can define | ||
| their own | ||
| function catalogs while preserving strict validation for the standard set. | ||
|
|
||
| This guide demonstrates how to create a `custom_catalog.json` that adds a string | ||
| `trim` function and a hardware query function (`getScreenResolution`). | ||
|
|
||
| ## 1. Define the Custom Catalog | ||
|
|
||
| Create a JSON Schema file (e.g., `custom_catalog.json`) that defines your | ||
| function parameters. | ||
|
|
||
| Use the `functions` property to define a map of function schemas. | ||
|
|
||
| ```json | ||
| { | ||
| "$schema": "https://json-schema.org/draft/2020-12/schema", | ||
| "$id": "https://example.com/schemas/custom_catalog.json", | ||
| "title": "Custom Function Catalog", | ||
| "description": "Extension catalog adding string trimming and screen resolution functions.", | ||
| "functions": { | ||
| "trim": { | ||
| "type": "object", | ||
| "properties": { | ||
| "call": { "const": "trim" }, | ||
| "returnType": { "const": "string" }, | ||
| "args": { | ||
| "type": "array", | ||
| "minItems": 1, | ||
| "maxItems": 2, | ||
| "prefixItems": [ | ||
| { | ||
| "$ref": "https://a2ui.dev/specification/v0_9/common_types.json#/$defs/DynamicString", | ||
| "description": "The string to trim." | ||
| }, | ||
| { | ||
| "$ref": "https://a2ui.dev/specification/v0_9/common_types.json#/$defs/DynamicString", | ||
| "description": "Optional. A set of characters to remove. Defaults to whitespace." | ||
| } | ||
| ] | ||
| } | ||
| }, | ||
| "required": ["call", "args"] | ||
| }, | ||
| "getScreenResolution": { | ||
| "type": "object", | ||
| "properties": { | ||
| "call": { "const": "getScreenResolution" }, | ||
| "returnType": { "const": "array" }, | ||
| "args": { | ||
| "type": "array", | ||
| "minItems": 0, | ||
| "maxItems": 1, | ||
| "prefixItems": [ | ||
| { | ||
| "$ref": "https://a2ui.dev/specification/v0_9/common_types.json#/$defs/DynamicNumber", | ||
| "description": "Optional. The index of the screen to query. Defaults to 0 (primary screen)." | ||
| } | ||
| ] | ||
| } | ||
| }, | ||
| "required": ["call"] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## 2. Make the functions available | ||
|
|
||
| The `FunctionCall` definition refers to a [catalog-agnostic reference](a2ui_protocol.md#the-standard-catalog). | ||
| In your catalog, you simply need to define the `anyFunctions` reference: | ||
| ```json | ||
| { | ||
| "$defs": { | ||
| "anyFunction": { | ||
| "oneOf": [ | ||
| {"$ref": "#/functions/trim"}, | ||
| {"$ref": "#/functions/getScreenResolution"} | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| If you want to incorporate functions defined in the [`standard_catalog.json`], | ||
| those can be added too: | ||
| ```json | ||
| { | ||
| "$defs": { | ||
| "anyFunction": { | ||
| "oneOf": [ | ||
| {"$ref": "#/functions/trim"}, | ||
| {"$ref": "#/functions/getScreenResolution"}, | ||
| {"$ref": "catalog.json#/$defs/anyFunction" } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## How Validation Works | ||
|
|
||
| When a `FunctionCall` is validated: | ||
|
|
||
| 1. **Discriminator Lookup:** The validator looks at the `call` property of the | ||
| object. | ||
| 2. **Schema Matching:** | ||
| * If `call` is "length", it matches `Functions` -> `length` | ||
| and validates the arguments against the length rules. | ||
| * If `call` is "trim", it matches `CustomFunctions` -> `trim` and | ||
| validates against your custom rules. | ||
| * If `call` is "unknownFunc": | ||
| * If `GenericFunction` is NOT included, validation FAILS immediately ( | ||
| strict mode). | ||
| * If `GenericFunction` IS included, it matches the generic fallback and | ||
| PASSES (loose mode). | ||
|
|
||
| This strict-by-default approach ensures typos are caught early, while the | ||
| modular structure makes it easy to add new capabilities. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -168,7 +168,10 @@ | |
| "default": "boolean" | ||
| } | ||
| }, | ||
| "required": ["call"] | ||
| "required": ["call"], | ||
| "oneOf": [ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we just leave this |
||
| { "$ref": "catalog.json#/$defs/anyFunction" } | ||
| ] | ||
| }, | ||
| "LogicExpression": { | ||
| "type": "object", | ||
|
|
||
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.
For consistency with other function definitions in this document and in
standard_catalog.json, thegetScreenResolutionfunction example should require theargsproperty. Even when a function has optional or no arguments, requiring anargsproperty (which can be an empty array) makes the function call structure uniform and more predictable for implementers.