Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the A2UI core blueprint to formalize the API/Implementation symmetry for both components and functions, introduce JSON catalog documents with serialization/deserialization rules, define renderer capabilities, and specify multi-version validation. The review feedback correctly identifies two inconsistencies in the updated blueprint: the InlineCatalog interface is missing the protocolVersion property required for structural parity with catalog documents, and the A2uiValidator class should be generic over TComponent and TFunction to align with the design rules specified in the document.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Polina Cherkasova <polina.c@live.com>
| 1. **Catalog Representation:** Define `Catalog` structures and pure technical component metadata/schemas (`ComponentApi`, `FunctionApi`). | ||
| 2. **Protocol Definitions:** Model strongly-typed inbound and outbound message structures (e.g., `RendererToAgent`, `AgentToRenderer`, etc.). | ||
| 1. **Catalog Representation:** Define `Catalog` structures and pure technical component metadata/schemas (`ComponentApi`, `FunctionApi`), including loading a catalog from, and serializing it back to, an A2UI **catalog document** (JSON). | ||
| 2. **Protocol Definitions:** Model strongly-typed inbound and outbound message structures (e.g., `RendererToAgent`, `AgentToRenderer`, etc.), including the `A2uiRendererCapabilities` negotiation payload, for every supported protocol version. |
There was a problem hiding this comment.
Should the supported version negotiation happen on the a2ui_core SDK?
I think it is the agent's responsibility to negotiate the supported protocol version and supported catalog IDs based on the renderer capabilities in the request. The renderer doesn't need to negotiate anything. It just sends what it supports.
| │ ├── catalog # Catalog base class (incl. fromJson / toJson) | ||
| │ ├── components # ComponentApi + schema-only JsonComponentApi | ||
| │ ├── functions # FunctionApi + FunctionImplementation | ||
| │ └── catalog_document # Catalog document reader/writer & `REF:` expansion |
There was a problem hiding this comment.
Do we need this as public interfaces? Can this be consolidated into the catalog class?
|
|
||
| /** | ||
| * The raw document this catalog was loaded from, when it was loaded via `fromJson()`; | ||
| * otherwise the document produced by `toJson()`. Implementations may cache it. |
There was a problem hiding this comment.
#1626 proposes to compute the property dynamically without caching.
| ): Catalog<ComponentApi, FunctionApi>; | ||
|
|
||
| /** Serializes this catalog back into an A2UI catalog document. */ | ||
| toJson(): Record<string, any>; |
There was a problem hiding this comment.
catalogSchema is basically the same as toJson. Can we remove the alias?
| | Pure declaration | `ComponentApi` | `FunctionApi` | No | | ||
| | Executable/renderable | `ComponentImplementation` | `FunctionImplementation` | Yes | | ||
|
|
||
| Rules: |
There was a problem hiding this comment.
Thanks. I like the clarification rules!
| 2. `Catalog` is generic over both: `Catalog<TComponent extends ComponentApi, TFunction extends FunctionApi>`. | ||
| 3. A **renderer** binds `Catalog<ComponentImplementation, FunctionImplementation>` — everything is executable. | ||
| 4. An **agent** binds `Catalog<ComponentApi, FunctionApi>` — declaration only. An agent must never need a stub implementation whose `execute` throws in order to hold a catalog; the type system makes that state unrepresentable. | ||
| 5. Every downstream generic that carries a catalog (`MessageProcessor`, `SurfaceGroupModel`, `SurfaceModel`, `A2uiValidator`, `NodeResolver`) carries both parameters. |
There was a problem hiding this comment.
With the mixed-catalog support, MessageProcessor and others actually carry a list of catalogs.
| }, | ||
| }, | ||
| "functions": [{"name": "now", "returnType": "string", "parameters": {"type": "object"}}], | ||
| "theme": {"primaryColor": {"type": "string"}}, |
There was a problem hiding this comment.
theme is no longer available in v1.0 catalog.
| - If the document declares a value and the caller supplied one, they MUST agree; a conflict raises `A2uiCatalogError` rather than silently loading a catalog the renderer never negotiated. | ||
| - If the document declares a value and the caller supplied none, the declared value wins. | ||
| - A missing declaration is not an error: `catalogId` is not defined in v0.8 and `protocolVersion` is not defined before v1.0. If neither the document nor the caller supplies a `catalogId`, raise `A2uiCatalogError`. | ||
| - A declared field of the wrong JSON type (e.g. a non-string `catalogId`) raises `A2uiValidationError`. |
There was a problem hiding this comment.
Should this be a A2uiCatalogError? I consider A2uiValidationError validates against A2UI payload, while A2uiCatalogError is for the catalog schema.
| 1. The envelope schema is selected per version from the versioned schema models under `schema/<version>/`. | ||
| 2. If `ValidationConfig.targetVersion` is set, payloads are validated against that version and a payload declaring a different `version` tag is rejected. | ||
| 3. If `targetVersion` is unset, the version is resolved from the message envelope's own `version` tag; an unrecognized tag raises `A2uiValidationError`. | ||
| 4. Version-specific field naming (e.g. `theme` in v0.8/v0.9 vs. `surfaceProperties` in v1.0+) is resolved through the same `VersionAdapter` the `MessageProcessor` uses, so validation and processing can never disagree about a field's location. |
There was a problem hiding this comment.
This is a bit outdated. surfaceProperties are removed from v1.0.
Contributes to #2356.