Skip to content

fix(swift/core): emit v1.0 inline catalogs without the ComponentCommon envelope - #3382

Open
karolkulesza wants to merge 16 commits into
a2ui-project:mainfrom
karolkulesza:fix/swift-v10-inline-catalog-envelope
Open

karolkulesza wants to merge 16 commits into
a2ui-project:mainfrom
karolkulesza:fix/swift-v10-inline-catalog-envelope

Conversation

@karolkulesza

@karolkulesza karolkulesza commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Description

Swift leg of #3061. It does not remove componentEnvelopeRef; that is left to the decision
in the issue.

v1.0 composes ComponentCommon in the message envelope (agent_to_renderer.json), and
specification/v1_0/docs/a2ui_protocol.md says catalog components "MUST NOT be redundantly
wrapped with ComponentCommon via allOf". web_core and Python only apply the envelope below
v1.0. Swift's MessageProcessor.getRendererCapabilities applied it for every version, and also
listed the @index system function under functions in every v1.0 inline catalog, although
the @ namespace is reserved for system functions.

Changes:

  • Swift (MessageProcessor.generateInlineCatalog): for v1.0 each component is
    {type: object, properties, required}, with the component const as before, plus the
    schema's description and the component's allowedParents, allowedChildren and metadata
    when set (JSONSchema.Schema drops those keywords, so they come from AnyComponentAPI), as
    web_core, Python and Dart emit them. v0.9 keeps the
    allOf envelope and still honours componentEnvelopeRef, whose doc comments now say it only
    applies before v1.0. v1.0 inline catalogs no longer declare @-prefixed functions, and
    functions is left out when no function remains.
  • Python (MessageProcessor.get_renderer_capabilities): a v1.0 inline catalog gets its
    catalogId and the bare protocolVersion (1.0), as web_core's generateInlineCatalog
    does. Before, Python left protocolVersion out when the catalog document did not declare it,
    and catalog_definition.json reads a missing protocolVersion as 0.9. A blank
    protocolVersion counts as undeclared, a leading v is stripped, and the to_json()
    document is copied rather than changed in place.
  • conformance: test_v10_get_renderer_capabilities_inline_catalogs in
    message_processor_v1_0.yaml, the first v1.0 capabilities case with
    includeInlineCatalogs: true.

Before this change the new case failed in Swift (envelope and @index) and in Python (no
protocolVersion); web_core and Dart pass it as they are.

Tests:

  • Swift: the conformance case, getRendererCapabilitiesWrapsComponentEnvelopeOnlyBeforeV10
    (one call for v0.9.1 and v1.0 with a custom componentEnvelopeRef),
    getRendererCapabilitiesKeepsV10ComponentDefinitionFields, and a check that @index is left
    out next to user functions. Full swift test passes; swift-format lint --strict is clean.
  • Python: unit tests in test_catalog_json.py for v prefix stripping, an undeclared or blank
    protocolVersion, the catalog_id override, and no in-place change to the to_json()
    document. Full python/a2ui_core pytest, mypy and pyink pass.
  • web_core: node tests/conformance/conformance_test.mjs passes.
  • Dart: message_processor_conformance_test.dart passes.

Known limit: Swift has no catalog toJSON, so it still rebuilds each inline component from its
schema, in both versions, as before.

Refs #3061

Pre-launch Checklist

One time:

For this PR:

  • I have updated the relevant CHANGELOG.md file.
  • I updated/added relevant documentation.
  • My code changes (if any) have tests.
  • If my branch is on a fork, I have verified that scripts/e2e_test.sh passes.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 updates the 'MessageProcessor' in both Python and Swift to correctly handle v1.0 inline catalogs. Specifically, v1.0 inline catalogs now omit the 'ComponentCommon' envelope (leaving components as plain schemas), format the 'protocolVersion' as a bare semantic version (e.g., '1.0' instead of 'v1.0'), and exclude system functions starting with '@'. Corresponding conformance and unit tests have been added. Feedback on the Python implementation suggests verifying that dynamically retrieved attributes are not callable before processing them to prevent potential runtime crashes.

@github-actions github-actions Bot added the status: needs-triage auto-managed: https://github.com/a2ui-project/a2ui/blob/main/scripts/triage.mjs label Oct 21, 2026
…n envelope

v1.0 composes ComponentCommon in the message envelope, and a2ui_protocol.md
says catalog components must not wrap it again. Swift's getRendererCapabilities
wrapped every inline component in allOf [ComponentCommon, ...] for every
version, and listed the @index system function in every v1.0 inline catalog.

- Swift: v1.0 inline components are plain {type, properties, required}
  schemas; @-prefixed functions are not declared. v0.9 output and
  componentEnvelopeRef are unchanged.
- Python: v1.0 inline catalogs get catalogId and the bare protocolVersion,
  as in web_core, also when the catalog document did not declare them.
- conformance: add test_v10_get_renderer_capabilities_inline_catalogs.

Refs a2ui-project#3061
….0 inline catalogs

_generate_inline_catalog reads catalog_id and protocol_version with getattr on a
duck-typed catalog; ignore them when they are methods instead of values, as
system_functions.py already does for index.
@karolkulesza
karolkulesza force-pushed the fix/swift-v10-inline-catalog-envelope branch from 88956e5 to f3e5bcc Compare October 22, 2026 16:13
@karolkulesza

Copy link
Copy Markdown
Contributor Author

Rebased onto main to resolve the python/a2ui_core/CHANGELOG.md conflict (kept both "Unreleased" entries); no code changes. Python a2ui_core tests and the Swift MessageProcessor tests pass on the rebased branch.

@karolkulesza

Copy link
Copy Markdown
Contributor Author

Merged main. #3582 split inline catalog generation into helpers, so this PR's three changes now live there:

  • buildInlineComponentSchema takes the protocol version and returns a plain component schema for v1.0.
  • generateV10InlineFunctions skips @-prefixed system functions.
  • An empty functions map is left out.

The new capabilities test and the conformance case now use the 1.0 wire version from #3726. All swift/core tests pass, and so do the Python, TypeScript and Dart core suites that run message_processor_v1_0.yaml.

Comment thread python/a2ui_core/CHANGELOG.md Resolved
@github-actions github-actions Bot removed the status: needs-triage auto-managed: https://github.com/a2ui-project/a2ui/blob/main/scripts/triage.mjs label Oct 29, 2026
@pinieb pinieb added status: waiting-for-author-response lang: swift Affects SDKs or apps in the Swift programming language labels Oct 30, 2026
@github-actions github-actions Bot added status: needs-triage auto-managed: https://github.com/a2ui-project/a2ui/blob/main/scripts/triage.mjs and removed status: waiting-for-author-response labels Oct 30, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lang: swift Affects SDKs or apps in the Swift programming language status: needs-triage auto-managed: https://github.com/a2ui-project/a2ui/blob/main/scripts/triage.mjs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants