Skip to content

feat(examples-chat): Phase 4 — generative UI / A2UI surfaces#226

Merged
blove merged 5 commits into
mainfrom
claude/examples-chat-phase-4-generative-ui
May 9, 2026
Merged

feat(examples-chat): Phase 4 — generative UI / A2UI surfaces#226
blove merged 5 commits into
mainfrom
claude/examples-chat-phase-4-generative-ui

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 9, 2026

Summary

Layers Generative UI / A2UI surfaces onto the canonical demo via a tool-driven, deterministic post-process render path. The parent AI dispatches a new `render_demo_form` tool; routing diverts to a new `emit_a2ui_surface` node that synthesizes a satisfying ToolMessage plus an AIMessage carrying the `---a2ui_JSON---` wire-format prefix and a hardcoded feedback-form JSONL surface spec. The existing `` composition's content classifier auto-detects the prefix and renders `` (already mounted by the composition); submitting the form's button round-trips through `agent.submit` with no extra plumbing.

  • Python graph: `A2UI_PREFIX` + `FEEDBACK_FORM_JSONL` constants, `render_demo_form` `@tool`, `emit_a2ui_surface` async node, `should_continue` extended with the new branch, conditional-edges map updated, new `emit_a2ui_surface → attach_citations` edge, bound on the parent in 2 places (`bind_tools`, `ToolNode`). Existing `tools → generate` loop unaffected for other tool calls. SYSTEM_PROMPT extended by one paragraph.
  • Welcome suggestion: 10th entry "Demo: render an interactive A2UI surface".
  • CHECKLIST.md: Generative UI / A2UI surfaces section populated.
  • Zero Angular shell wiring: `` already imports `A2uiSurfaceComponent` and routes form-action messages through `agent.submit`.

Hardcoded JSONL because A2UI's schema-exact format is not a reliable LLM capability today (cockpit author's documented constraint at `cockpit/chat/a2ui/python/src/graph.py`). The AI decides when to render; Python pins the schema correctness.

Spec: `docs/superpowers/specs/2026-05-09-canonical-chat-demo-phase-4-generative-ui-design.md`
Plan: `docs/superpowers/plans/2026-05-09-canonical-chat-demo-phase-4-generative-ui.md`

Test plan

Verified locally

  • `nx run examples-chat-python:smoke` — 11 passed (8 existing + 3 new)
  • `nx run examples-chat-angular:test` — 9 passed
  • `nx run examples-chat-angular:lint` — 0 errors
  • `nx run examples-chat-angular:build` — succeeds (development)
  • Server-side end-to-end probe: submit the welcome prompt with model=gpt-5-mini. 4 messages: AI tool_call `name: 'render_demo_form'`, `args: {"form_type":"feedback"}`; ToolMessage `content: 'rendered'`; final AI message whose content starts with `---a2ui_JSON---\n{"createSurface": {"surfaceId": "feedback", "catalogId": "basic", "sendDataModel": true}}\n{"updateDataMo...`.

Pending visual verification

  • After merge: live smoke against the workspace `examples/chat` demo. Assistant bubble renders an `` Card titled "Quick feedback" with a TextField, a ChoicePicker, and a Submit button. Required-name validation works. Click Submit → AI replies conversationally referencing the form.

(Visual sweep continues against issue #214; rolls together with the next iteration.)

🤖 Generated with Claude Code

blove and others added 5 commits May 9, 2026 10:55
…aces

Adds a tool-driven A2UI surface render path: render_demo_form @tool the
parent LLM dispatches; routing diverts to a new emit_a2ui_surface node
that synthesizes the satisfying ToolMessage plus an AIMessage carrying
the ---a2ui_JSON--- wire-format prefix and a hardcoded feedback-form
JSONL surface spec. Existing chat composition's content classifier
auto-detects the prefix and renders <a2ui-surface>; submit round-trips
through agent.submit with no extra plumbing. Hardcoded JSONL because
A2UI's schema-exact format is not a reliable LLM capability today.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…aces plan

Single-subagent-dispatch plan for Phase 4. ~100 LOC across 5 phased
tasks (Phases 0-4). TDD'd python graph (render_demo_form tool +
emit_a2ui_surface node + routing branch + JSONL constants), welcome
suggestion, CHECKLIST, server-side verification probe, and PR open.
Mirrors Phase 3A/3B plan format. Zero Angular shell wiring.

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 Building Building Preview, Comment May 9, 2026 5:58pm

Request Review

@blove blove merged commit d686735 into main May 9, 2026
13 of 14 checks passed
blove added a commit that referenced this pull request May 9, 2026
#227)

* fix(chat,examples-chat): wire a2uiBasicCatalog so A2UI surfaces actually 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>

* docs(chat): regenerate API docs for new chat-popup/sidebar views input

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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