Skip to content

fix(chat,examples-chat): wire a2uiBasicCatalog so A2UI surfaces render#227

Merged
blove merged 2 commits into
mainfrom
claude/fix-examples-chat-a2ui-catalog
May 9, 2026
Merged

fix(chat,examples-chat): wire a2uiBasicCatalog so A2UI surfaces render#227
blove merged 2 commits into
mainfrom
claude/fix-examples-chat-a2ui-catalog

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 9, 2026

Summary

Phase 4 (PR #226) shipped a working python graph that produces an AIMessage with the `---a2ui_JSON---` wire-format prefix; the chat composition's content classifier correctly identifies the message as A2UI and parses the surface. However, the template gates the final mount on `@if (classified.type() === 'a2ui' && views(); as catalog)` — without a `views` ViewRegistry, the surface never reaches the DOM and the message renders as a tool-call card instead of the Card with the declared TextField / ChoicePicker / Button.

Two changes:

  1. chat-popup + chat-sidebar (libs/chat): forward a `views` input through to the inner ``. Both compositions wrapped `<chat [agent]>` directly with no pass-through, leaving popup/sidebar consumers unable to render surfaces even after wiring the catalog.
  2. examples/chat/angular: import `a2uiBasicCatalog` from `@ngaf/chat` in all three mode components (embed, popup, sidebar) and pass the result as `[views]`.

Verification

Live smoke against the workspace examples/chat demo after the fix:

  • Click "Demo: render an interactive A2UI surface" → AI emits `render_demo_form` tool_call ✅
  • Routing diverts to `emit_a2ui_surface` → ToolMessage("rendered") + AIMessage starting with `---a2ui_JSON---\n` ✅
  • Content classifier reports `type: 'a2ui'`, `a2uiSurfaces.size: 1` ✅
  • `` mounts in the chat-message bubble with the full subtree: ``, `` ("Type your name"), `` (rating 1-5), `` ("Submit feedback") ✅
  • Card title "Quick feedback" renders as designed ✅
  • Lint + build + tests for both `chat` and `examples-chat-angular` projects pass

Out of scope

Form input → dataModel back-propagation (Finding K): the A2UI text-field emits `a2ui:datamodel:/path:value` events when the user types, but no consumer in libs/chat or libs/render parses these events and updates the surface store. The form's required-name validation thus never sees the typed value, leaving Submit disabled. This is a separate lib-level gap — to be tracked in a follow-up issue.

Test plan

  • CI green (chat lib + examples-chat-angular)
  • No regressions in /embed, /popup, /sidebar mode rendering for non-A2UI messages

🤖 Generated with Claude Code

…lly render

Phase 4 (PR #226) shipped a working python graph that produces an
AIMessage with the ---a2ui_JSON--- wire-format prefix; the chat
composition's content classifier correctly identifies the message as
a2ui and parses the surface (size=1). However, the template gates the
final mount on `@if (classified.type() === 'a2ui' && views(); as catalog)`
— without a `views` ViewRegistry, the surface never reaches the DOM
and the message renders as a tool-call card instead of a Card with the
declared TextField / ChoicePicker / Button.

Two changes:

1. **chat-popup + chat-sidebar**: forward a `views` input through to
   the inner `<chat>`. They wrapped `<chat [agent]>` directly with no
   way to pass A2UI catalog through, leaving popup/sidebar consumers
   unable to render surfaces even after wiring.

2. **examples/chat/angular**: import `a2uiBasicCatalog` from
   `@ngaf/chat` in all three mode components and pass the result as
   `[views]`. The demo now renders the feedback Card on the
   render_demo_form path in /embed, /popup, and /sidebar.

Verified live: clicking the welcome suggestion produces the AI tool
call → ToolMessage("rendered") → AIMessage with prefix + JSONL → the
chat-message bubble mounts <a2ui-surface> with <a2ui-card>,
<a2ui-text-field>, <a2ui-choice-picker>, <a2ui-button>. The Card title
"Quick feedback" displays as designed. Lint + build + tests for both
chat lib and examples-chat-angular all pass.

A separate lib-level gap (a2ui:datamodel:* emit events have no
consumer wiring up to the surface store) prevents form input from
back-propagating to the dataModel; that's outside Phase 4 scope and
will be tracked separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cacheplane Ready Ready Preview, Comment May 9, 2026 6:49pm

Request Review

@blove blove merged commit b8e3bca into main May 9, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant