feat(a2ui): chat add action request and response#2667
Conversation
|
📝 WalkthroughWalkthroughThis PR implements a complete action-streaming workflow for the A2UI playground. It restructures Button component schemas to use nested action payloads, threads a ChangesLiveAction Action Streaming Feature
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/genui/server/agent/a2ui-validator.ts (1)
282-289:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnforce the new Button schema in validator, not just
action.event.name.
Buttonnow requires achildid and deprecates inlinelabel, but this validator block only checksaction.event.name. Schema-invalid Button payloads can still pass validation.Suggested patch
if (requiresAction.has(comp.component)) { const action = comp.action; if (!hasActionName(action)) { errors.push( `${comp.component} (id=${comp.id}) MUST carry action.event.name.`, ); } } + if (comp.component === 'Button') { + if (typeof comp.child !== 'string' || comp.child.length === 0) { + errors.push( + `Button (id=${comp.id}) MUST carry a non-empty "child" component id.`, + ); + } + if ('label' in (comp as Record<string, unknown>)) { + errors.push( + `Button (id=${comp.id}) MUST NOT include "label"; use a child Text component.`, + ); + } + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/genui/server/agent/a2ui-validator.ts` around lines 282 - 289, The validator currently only enforces hasActionName for components in requiresAction; extend that logic to fully validate Button payloads: when comp.component === 'Button' (and when requiresAction.has(comp.component) applies), check comp.action as before (using hasActionName) AND verify the Button-specific schema—ensure a child id is present (e.g., comp.child or comp.childId) and reject/emit an error if an inline label is present (e.g., comp.props?.label) since label is deprecated; push clear messages onto errors for missing child id and for deprecated inline label using the same errors array and context (comp.component, comp.id).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/genui/a2ui-playground/src/pages/AIChatPage.css`:
- Around line 128-132: Rename the `@keyframes` identifier chatMessageActionSpin to
kebab-case (e.g., chat-message-action-spin) and update every usage of that
keyframe (animation, animation-name, and any JS/React references that inject or
reference the animation) to the new name; ensure you update symbols in CSS
classes/selectors where animation: chatMessageActionSpin ... or animation-name:
chatMessageActionSpin appears so stylelint no longer reports the kebab-case
violation.
In `@packages/genui/a2ui-playground/src/pages/AIChatPage.tsx`:
- Around line 130-135: The getA2UIActionStreamEndpoint function currently relies
on a regex replace that will silently return the original URL if
getA2UIChatEndpoint() doesn't end with "/a2ui/stream"; update
getA2UIActionStreamEndpoint to validate the returned chat endpoint (call
getA2UIChatEndpoint())—if it matches the expected suffix, perform the
replacement to "/a2ui/action/stream", otherwise either construct the action
stream endpoint deterministically (e.g., by ensuring the base path and appending
"/a2ui/action/stream") or throw/log a clear error; reference
getA2UIActionStreamEndpoint and getA2UIChatEndpoint when locating the code and
add a defensive check and explicit handling for non-matching inputs.
- Around line 649-853: The action streaming flow in handleMessage lacks
cancellation so in-flight fetches can update state after unmount or when new
actions arrive; add an AbortController ref (e.g., actionAbortRef via
useRef<AbortController | null>) and before starting a new action abort any
existing controller, pass controller.signal to window.fetch (and into
readA2UIResponse if it accepts a signal), check signal.aborted inside streaming
callbacks before calling setMessages or posting to previewFrameRef, and in the
effect cleanup abort the current controller; ensure you clear actionAbortRef
when the request finishes or fails so subsequent actions create fresh
controllers.
In `@packages/genui/server/app/a2ui/action/stream/route.ts`:
- Around line 72-80: Change the two validation early-returns that check
body.threadId and body.action.name so they return a 400 Bad Request instead of
the default 200; specifically update the handlers around the checks for "if
(!body || !body.threadId)" and "if (!body.action || !body.action.name)" to call
jsonWithCors (or set the response status) with HTTP status 400 and the same
error payload (e.g., { ok: false, error: '...' }) so clients receive a proper
400 response.
---
Outside diff comments:
In `@packages/genui/server/agent/a2ui-validator.ts`:
- Around line 282-289: The validator currently only enforces hasActionName for
components in requiresAction; extend that logic to fully validate Button
payloads: when comp.component === 'Button' (and when
requiresAction.has(comp.component) applies), check comp.action as before (using
hasActionName) AND verify the Button-specific schema—ensure a child id is
present (e.g., comp.child or comp.childId) and reject/emit an error if an inline
label is present (e.g., comp.props?.label) since label is deprecated; push clear
messages onto errors for missing child id and for deprecated inline label using
the same errors array and context (comp.component, comp.id).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 47bef139-0666-4a6d-b2ee-36253627e7e4
📒 Files selected for processing (11)
packages/genui/a2ui-playground/lynx-src/a2ui/App.tsxpackages/genui/a2ui-playground/src/pages/AIChatPage.csspackages/genui/a2ui-playground/src/pages/AIChatPage.tsxpackages/genui/a2ui-playground/src/render.tsxpackages/genui/a2ui-playground/src/utils/renderUrl.tspackages/genui/server/agent/a2ui-catalog.tspackages/genui/server/agent/a2ui-prompt.tspackages/genui/server/agent/a2ui-validator.tspackages/genui/server/app/a2ui/action/stream/route.tspackages/genui/server/app/a2ui/stream/route.tspackages/genui/server/service/a2ui-agent.ts
Merging this PR will not alter performance
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ❌ | 002-hello-reactLynx-destroyBackground |
669.9 µs | 916.7 µs | -26.93% |
| ⚡ | transform 1000 view elements |
45.9 ms | 41.9 ms | +9.66% |
| ⚡ | basic-performance-large-css |
19 ms | 16.1 ms | +17.48% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing Sherry-hue:feat/chat-action (eddbe61) with main (8aebe79)
Footnotes
-
26 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
c04ed04 to
eddbe61
Compare
Web Explorer#10034 Bundle Size — 903.49KiB (~-0.01%).eddbe61(current) vs 531ef76 main#10033(baseline) Bundle metrics
Bundle size by type
Bundle analysis report Branch Sherry-hue:feat/chat-action Project dashboard Generated by RelativeCI Documentation Report issue |
React Example#8460 Bundle Size — 237.24KiB (0%).eddbe61(current) vs 531ef76 main#8459(baseline) Bundle metrics
|
| Current #8460 |
Baseline #8459 |
|
|---|---|---|
0B |
0B |
|
0B |
0B |
|
0% |
0% |
|
0 |
0 |
|
4 |
4 |
|
198 |
198 |
|
80 |
80 |
|
44.74% |
44.74% |
|
2 |
2 |
|
0 |
0 |
Bundle size by type no changes
| Current #8460 |
Baseline #8459 |
|
|---|---|---|
145.76KiB |
145.76KiB |
|
91.48KiB |
91.48KiB |
Bundle analysis report Branch Sherry-hue:feat/chat-action Project dashboard
Generated by RelativeCI Documentation Report issue
React Example with Element Template#729 Bundle Size — 200.08KiB (0%).eddbe61(current) vs 531ef76 main#728(baseline) Bundle metrics
Bundle size by type
|
| Current #729 |
Baseline #728 |
|
|---|---|---|
145.76KiB |
145.76KiB |
|
54.32KiB |
54.32KiB |
Bundle analysis report Branch Sherry-hue:feat/chat-action Project dashboard
Generated by RelativeCI Documentation Report issue
React MTF Example#1593 Bundle Size — 208.18KiB (0%).eddbe61(current) vs 531ef76 main#1592(baseline) Bundle metrics
|
| Current #1593 |
Baseline #1592 |
|
|---|---|---|
0B |
0B |
|
0B |
0B |
|
0% |
0% |
|
0 |
0 |
|
3 |
3 |
|
193 |
193 |
|
77 |
77 |
|
44.24% |
44.24% |
|
2 |
2 |
|
0 |
0 |
Bundle size by type no changes
| Current #1593 |
Baseline #1592 |
|
|---|---|---|
111.23KiB |
111.23KiB |
|
96.95KiB |
96.95KiB |
Bundle analysis report Branch Sherry-hue:feat/chat-action Project dashboard
Generated by RelativeCI Documentation Report issue
React External#1575 Bundle Size — 695.64KiB (0%).eddbe61(current) vs 531ef76 main#1574(baseline) Bundle metrics
|
| Current #1575 |
Baseline #1574 |
|
|---|---|---|
0B |
0B |
|
0B |
0B |
|
0% |
0% |
|
0 |
0 |
|
3 |
3 |
|
17 |
17 |
|
5 |
5 |
|
8.59% |
8.59% |
|
0 |
0 |
|
0 |
0 |
Bundle analysis report Branch Sherry-hue:feat/chat-action Project dashboard
Generated by RelativeCI Documentation Report issue
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/genui/server/agent/a2ui-prompt.ts`:
- Around line 149-152: The few-shot example is embedding a secret ("password")
into action.event.context which can leak plaintext credentials; update the
example in a2ui-prompt.ts to remove or replace the "password" field with a
non-secret placeholder (e.g., "userId" or "demo_password_placeholder") and add a
short inline comment or a bullet in the surrounding prompt text enforcing a hard
rule: never include secrets (passwords/tokens/keys) in action.event.context.
Locate the example object containing "context" (the example action/event
payload) and change the key/value accordingly and add the explicit rule near
that example so future examples follow the non-secret pattern.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ffd6b5be-3b0f-47d0-aa2c-18070b31e8c9
📒 Files selected for processing (11)
packages/genui/a2ui-playground/lynx-src/a2ui/App.tsxpackages/genui/a2ui-playground/src/pages/AIChatPage.csspackages/genui/a2ui-playground/src/pages/AIChatPage.tsxpackages/genui/a2ui-playground/src/render.tsxpackages/genui/a2ui-playground/src/utils/renderUrl.tspackages/genui/server/agent/a2ui-catalog.tspackages/genui/server/agent/a2ui-prompt.tspackages/genui/server/agent/a2ui-validator.tspackages/genui/server/app/a2ui/action/stream/route.tspackages/genui/server/app/a2ui/stream/route.tspackages/genui/server/service/a2ui-agent.ts
🚧 Files skipped from review as they are similar to previous changes (9)
- packages/genui/server/service/a2ui-agent.ts
- packages/genui/a2ui-playground/src/utils/renderUrl.ts
- packages/genui/server/agent/a2ui-validator.ts
- packages/genui/a2ui-playground/lynx-src/a2ui/App.tsx
- packages/genui/server/app/a2ui/stream/route.ts
- packages/genui/a2ui-playground/src/render.tsx
- packages/genui/server/agent/a2ui-catalog.ts
- packages/genui/a2ui-playground/src/pages/AIChatPage.tsx
- packages/genui/server/app/a2ui/action/stream/route.ts
Summary by CodeRabbit
New Features
Improvements
Checklist