feat(web_core)!: resolve catalogId overrides through per-surface catalogs - #2715
Open
gspencergoog wants to merge 3 commits into
Open
gspencergoog wants to merge 3 commits into
gspencergoog wants to merge 3 commits into
Conversation
…logs
TypeScript accepted a `catalogId` on a component but had nowhere to put one
on a function call, and had no notion of which catalogs a given surface may
address. This brings it in line with Python's multi-catalog model.
`SurfaceModel` now carries `availableCatalogs`, the subset of registered
catalogs whose protocol version is compatible with the surface's own.
`MessageProcessor` populates it on `createSurface`, and component and
function lookups resolve through it. A function call naming a catalog the
surface cannot reach raises `A2uiCatalogError`, and its arguments are
validated against the catalog that will run it rather than against the
surface default.
Two reference-resolution bugs fall out of the same work:
- The integrity checker treated every string inside a structured array item
as a component reference, so `Tabs.tabs: [{title, child}]` failed with
`Dangling reference 'Overview'` where Python passed. `ComponentRefMap` now
records which item sub-keys the catalog declares as children, mirroring
Python's `nested_refs`.
- `schema_loader` collapsed any inline `type: object` into
`z.record(z.unknown())`, discarding its properties, so a child reference
nested inside an array item was invisible to the reference map for every
JSON-loaded catalog.
Also adds `A2uiCatalogError` and puts `catalogId` on the superset
`FunctionCall` schema. The field was already in the v1.0 schema; the superset
generator missed it because v1.0's `FunctionCall` has no direct `properties`,
only an `allOf`, which the generator now inlines.
Two conformance cases bind the other SDKs to both behaviours: a `catalogId`
override on a function call, and a structured-array child reference beside a
plain string sibling.
BREAKING-CHANGE: `Catalog`'s constructor takes `protocolVersion` as its
second argument and requires it, matching Python's ordering.
`Catalog.fromSchema` and `loadCatalogFromSchema` take an optional
`protocolVersion` for catalog schemas published before v1.0, which omit the
field.
BREAKING-CHANGE: `SurfaceModel.catalog` is renamed to `defaultCatalog`, and
`availableCatalogs` is inserted as the third constructor argument. `catalog`
remains as a deprecated getter and will be removed in a future release.
- Defensively fall back to surface.catalog in DataContext constructor and resolveFunctionCatalog when surface.defaultCatalog is undefined, and use optional chaining for surface.availableCatalogs. - Support both single child references and child lists within structured array items in inspectRawProperties. - Pass a cloned seen set down each recursive branch in inlineAllOfRefs to support diamond dependencies while guarding recursion cycles. - Forward available_catalogs through component validation in Python MessageProcessor and PayloadValidator, resolving nested function calls with catalogId overrides. - Revert samples/community modifications to maintain compatibility with the published @a2ui/web_core packages used by standalone community samples. - Add regression tests in web_core and a2ui_core.
- In TypeScript reference-map.ts, call addNestedRef when subRes.isChildList matches in both inspectShapeField and inspectRawProperties. - In integrity-checker.ts, recursively delegate to extractPointers for nestedKeys sub-keys rather than assuming single string child references. - In Python reference_map.py, include child lists in nested_refs derivation and extract_child_references traversal to preserve cross-SDK parity. - Add regression tests in web_core and a2ui_core.
gspencergoog
added this pull request to stack #2719
September 21, 2026 23:51
gspencergoog
removed this pull request from stack #2719
September 21, 2026 23:52
gspencergoog
added this pull request to stack #2720
September 21, 2026 23:52
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Aligns the TypeScript SDK (
web_core) with Python's multi-catalog model by introducing per-surface catalog scoping and routingcatalogIdoverrides for function calls and components. It also fixes two child-reference resolution defects where structured array sub-properties were either over-extracted as dangling references or omitted from catalog schemas entirely.Changes
availableCatalogs: ReadonlyMap<string, Catalog>toSurfaceModel, populated duringcreateSurfaceby filtering registered catalogs to those with compatible protocol versions. Component and function-call lookups now resolve through this map rather than assuming a single global catalog.catalogIdthroughDataContext.resolveFunctionCatalogandevaluateFunctionReactive. When a function call specifies acatalogId, its arguments are validated against that specific catalog and executed using that catalog's invoker. Calls specifying an unresolved catalog raiseA2uiCatalogError.catalogIdtoActionPayloadinSurfaceModel.dispatchActionwhen the triggering event payload names a catalog explicitly.A2uiCatalogError(inheriting fromA2uiError, default code'CATALOG_ERROR') insrc/errors.tsto represent catalog loading, registration, and resolution failures.new Catalog(id, protocolVersion, components, functions, ...)to makeprotocolVersionrequired and positional, matching Python's constructor order. Updated all call sites and test suites across the repository.loadCatalogFromSchemaandCatalog.fromSchemato accept an optionalprotocolVersionparameter for pre-v1.0 catalogs that lack an inline version field.nestedRefs?: Readonly<Record<string, ReadonlySet<string>>>toComponentRefMapand updatedinspectShapeField/extractPointers. In structured array items (e.g.,Tabs.tabs: [{title, child}]), only sub-keys declared by the catalog as child references are extracted; sibling string values (such as tab titles) are no longer treated as component IDs.convertPropertyToZodinschema_loader.tsto preserve properties for inlinetype: objectdefinitions rather than collapsing them toz.record(z.unknown()).scripts/generate-superset-common-types.mjsto inlineallOfreferences so thatcatalogIdfrom v1.0FunctionCallis included in the generated supersetFunctionCallSchema.test_topology_structured_array_child_ref_ignores_sibling_stringsinconformance/core/message_processor_v0_9.yamltest_multi_catalog_function_call_catalog_id_overrideinconformance/core/multi_catalog.yamlImpact & Risks
Catalognow requiresprotocolVersionas its second argument (Catalog(id, protocolVersion, ...)). External custom catalogs must pass their protocol version explicitly.SurfaceModel.catalogwas renamed todefaultCatalogto reflect that surfaces support multiple available catalogs. A deprecated gettercatalogis retained for backwards compatibility and will be removed in a subsequent release.SurfaceModelnow acceptsavailableCatalogsas its third parameter, shifting optional parameterstheme,sendDataModel, anddataModel. All in-tree callers and test mocks have been updated.Testing
web_core:yarn workspace @a2ui/web_core testyarn workspaces foreach -A -t run build yarn workspaces foreach -A -p -j 8 run test