Commit c2cbda5
feat(c-a2ui): LLM-driven aviation booking form (PR 4 of 4) (#380)
* docs: spec PR 4 — c-a2ui LLM-driven aviation booking form
Final PR of the c-* aviation rollout. Replaces the hardcoded contact
form with an LLM-authored booking form that emits valid A2UI JSONL via
.with_structured_output() + Pydantic schemas. Post-submit emits a
SECOND LLM-authored surface listing matching flights from
find_routes(). Retry policy: 2 retries on validation failure, then
hardcoded sentinel fallback.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* docs: plan PR 4 — c-a2ui LLM-driven aviation booking form
11 tasks: Pydantic schemas + envelope helper, LLM with structured output
+ retry, build_form / search_flights / route nodes, 3-node graph compile,
real-LLM smoke, standalone mirror with inlined flight fixtures, build
verification, REQUIRED iterative chrome MCP smoke, PR open.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(c-a2ui): pydantic schemas + envelope wrapper (foundation)
* feat(c-a2ui): gpt-5 structured-output LLM + retry helper
* feat(c-a2ui): build_form node — LLM-authored booking form + sentinel fallback
* feat(c-a2ui): search_flights node — LLM-authored results surface
* feat(c-a2ui): route node + 3-node graph compile
* feat(c-a2ui standalone): mirror LLM-driven booking form + inlined flight fixtures
* fix(c-a2ui): use function_calling structured-output (open dicts unsupported by strict mode)
* fix(c-a2ui): use A2UI v0.9 nested ComponentDef format
The chat-lib's unwrapComponentDef() expects {id, component: {<Name>:
{<props>}}} (single-key inner dict) — NOT my prior flat {id, component:
"Name", ...props}. Unknown component types silently fall through to a
stub Text and render nothing visible.
Also corrected:
- ChoicePicker → MultipleChoice (catalog name)
- NumberField → TextField with textFieldType="number"
- DatePicker → TextField with textFieldType="date"
- Card takes single `child` (not children list) — wrap multi-field forms
in a Card→Column→[fields...]
- Button needs `child` pointing at a Text component (label) + action
- children format is {explicitList: [...]}
- MultipleChoice uses `selections` (plural) + options=[{label,value}]
Updated:
- A2uiComponent schema → component: dict[str, dict[str, Any]] with
field_validator enforcing single key from ALLOWED_COMPONENTS frozenset
- Build_form / search_flights system prompts: complete v0.9 component
cheatsheet + exact id-tree spec + per-component shape examples
- Both sentinel forms rewritten in nested format
Mirrored to standalone (cockpit/chat/a2ui/python/src/graph.py).
Verified end-to-end: build_form produces 11 components in nested format;
search_flights for LAX→JFK produces 8 components including UA123 flight
Card + Select Button.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(c-a2ui): use correct A2UI v0.9 envelope keys (surfaceUpdate/dataModelUpdate/beginRendering)
* fix(c-a2ui): v0.9 ActionMessage submit detection + include form data in submit context
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>1 parent 6bdae46 commit c2cbda5
4 files changed
Lines changed: 2024 additions & 168 deletions
File tree
- cockpit
- chat/a2ui/python/src
- langgraph/streaming/python/src
- docs/superpowers
- plans
- specs
0 commit comments